public class SomeNamespaceTest extends TestCase {
/**
* 로거 설정
*/
private final Logger logger = LoggerFactory.getLogger(SomeNamespace.class);
private ApplicationContext context;
protected void setUp() throws Exception {
super.setUp();
this.context = new FileSystemXmlApplicationContext(new String[] {"./config/runtime/service/service-sample.xml"});
}
public void testNamespace() throws Exception {
ServiceDefinition service = (ServiceDefinition)context.getBean("sample");
assertEquals("sample", service.getId());
assertEquals("샘플 명", service.getName());
assertEquals("test_01", service.getRef());
assertEquals("샘플 서비스 설정에 대한 설명 입니다.", service.getDescription());
assertEquals(false, service.getAvailable());
assertEquals("aaa002", service.getNotAvailableMessageId());
ServiceDefinition service1 = (ServiceDefinition)context.getBean("sample1");
assertEquals("sample1", service1.getId());
assertEquals("sample1", service1.getName());
assertEquals("test_02", service1.getRef());
assertEquals("샘플 서비스 설정에 대한 설명 입니다.", service1.getDescription());
assertEquals(true, service1.getAvailable());
assertEquals("bbb001", service1.getNotAvailableMessageId());
ServiceGroupDefinition sg1 = (ServiceGroupDefinition)context.getBean("sample-group1");
assertEquals("sample-group1", sg1.getId());
assertEquals("샘플 그룹 1", sg1.getName());
assertEquals("샘플 서비스 그룹1에 대한 설명 입니다.", sg1.getDescription());
List sg1List = sg1.getTempServiceList();
assertEquals("sample", sg1List.get(0));
assertEquals("sample1", sg1List.get(1));
PreProcessorDefinition pre = (PreProcessorDefinition)context.getBean("pre_processor_01");
assertEquals("pre_processor_01", pre.getId());
assertEquals("테스트 프리 프로세서 01", pre.getName());
assertEquals("test_pre_01", pre.getRef());
assertEquals("샘플 pre_processor 설정에 대한 설명 입니다.", pre.getDescription());
PostProcessorDefinition post = (PostProcessorDefinition)context.getBean("post_processor_01");
assertEquals("post_processor_01", post.getId());
assertEquals("테스트 포스트 프로세서 01", post.getName());
assertEquals("test_post_01", post.getRef());
assertEquals("샘플 post_processor 설정에 대한 설명 입니다.", post.getDescription());
assertEquals(true, post.isFailOnError());
ProcessTemplateDefinition pt1 = (ProcessTemplateDefinition)context.getBean("process_template_01");
assertEquals("process_template_01", pt1.getId());
assertEquals("테스트 프로세스 템플릿", pt1.getName());
assertEquals("샘플 프로세스 템플릿 설정에 대한 설명 입니다.", pt1.getDescription());
List preList = pt1.getPreProcessorList();
List postList = pt1.getPostProcessorList();
assertEquals("pre_processor_01", preList.get(0));
assertEquals("post_processor_01", postList.get(0));
}
}
첫 번째 개선할 사항은 test 메소드를 수행할 때마다 매번 Application context를 로딩하지 않도록 캐싱을 이용하는 것입니다. 이프릴 공개 세미나에서 다룬 내용이죠. 저는 사정이 있어서 JUnit 3.8 라이브러리를 이용하겠습니다. 일반적인 상황이라면 JUnit 4를 쓰는 것이 좋겠죠. JUnit 4로 실행하시려면
스프링 레퍼런스 매뉴얼을 참조하시면 됩니다.
3.8 이용시는 AbstractDependencyInjectionSpringContextTests를 활용하여 DI까지 활용한 테스트가 가능합니다. 우선 다음과 같이 상속하는 클래스를 변경해주시고
public class HoneNamespaceTest extends
AbstractDependencyInjectionSpringContextTests {
멤버 변수로 설정한
context 대신에 테스트 대상으로 사용할 객체를 선언해주세요.
private ServiceDefinition sample;
그리고, DI를 위한 getter를 추가합니다.
public void setSample(ServiceDefinition sample) {
this.sample = sample;
}
AbstractDependencyInjectionSpringContextTests는 Autowiring을 지원해주는데 저는 By Name 방식을 쓸 예정입니다. 디폴트는 AUTOWIRE_BY_TYPE인지라, 다음과 같이 변경합니다. 얼핏 생각하면 setUp()을 대신하는 hook인 onSetUp()에서 설정해야 할 것처럼 보이지만, 생성자에서 해야 합니다.
public SomeNamespaceTest() { setAutowireMode(AUTOWIRE_BY_NAME); }그 이유는 onSetUp()이 인젝션이 수행되는 prepareTestInstance() 다음에 수행되기 때문이죠.
이렇게 하면 테스트
수행 속도를 개선할 수 있습니다. 한가지 빠뜨렸군요. context 파일 로딩은 템플릿 메소드를 쓰도록 바꾸셔야죠.
protected String getConfigPath() {
return "service-sample.xml";
}
쾌적한 테스트를 위해서 수행 속도 개선은 중요한 문제이긴 하지만 테스트의 본질은 아닙니다. 위의 테스트는 테스트 자체가 너무 길어서 냄새(Toooo long 냄새)가 납니다. ^^;
테스트의 목적을 분명히 하고, 향후 운영 시점에서 Regression Test가 가능하게 하려면 테스트 메소드의 가독성을 높이는 작업이 필요합니다. 흠 이건... 작업자에게 숙제로 남겨줘야겠군요. 테스트 코드에서 한 단락 단위로 테스트 메소드를 만들어주면 대강은 작업자의 의도와 드러맞겠죠.