본문 바로가기

백엔드/Spring

[jUnit] Spring 3.2.3 + myBatis 3.2 Test suite 적용.


현재 작업하고 있는 프로젝트의 모든 프레임워크를 최신버전으로 세팅을 하고 서비스 클래스를 jUnit으로 작성해보았다...


Maven jUnit dependency
1
2
3
4
5
6
<dependency>
    <groupid>junit</groupid>
    <artifactid>junit</artifactid>
    <version>4.7</version>
    <scope>test</scope>
</dependency>


Maven Spring framework test
1
2
3
4
5
<dependency>
    <groupid>org.springframework</groupid>
    <artifactid>org.springframework.test</artifactid>
    <version>3.2.3.RELEASE</version>
</dependency>




AbstractApplicationContextTest.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.openerp.service.test;
 
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
        "file:src/resources/applicationContext-datasource.xml",
        "file:src/resources/applicationContext-transaction.xml",
        "file:src/resources/applicationContext.xml"
            })
public class AbstractApplicationContextTest {
    @Autowired ApplicationContext ctx;
}

여기서 ContextConfiguration의 locations이 문제가 많다.
일반적인 설정으로 dataSource, transaction, AOP 설정등 모든걸 하나의 xml에 설정을 한다면 하나만 쓰면 되지만, 위 처럼 각 기능별(또는 업무별)로 설정을 나누어 버리면 위 처럼 순서를 맞추어 주어야 한다.
그리고 applicationContext 파일의 위치가 조금 달라지면 classpath를 쓸때 생각을 많이 해야 한다.


ApplicationContext.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!-- Annotation 기반의 Component Scan 필터(service package와 dao package만 검색) -->
<context:component-scan base-package="com.openerp">
    <context:include-filter type="regex" expression="\.*\.service\.*">
</context:include-filter></context:component-scan>
 
<!-- myBATIS 3.2.3 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  <property name="dataSource" ref="dataSource">
  <property name="configLocation" value="classpath:SqlMapConfig.xml"></property>
  <property name="mapperLocations" value="classpath:com/openerp/**/*SQL.xml"></property>
  <!-- not use this transactionFactory because use spring transactionFactory  -->
  <property name="transactionFactory">
        <bean class="org.mybatis.spring.transaction.SpringManagedTransactionFactory"></bean>
  </property>
</property></bean>
 
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="com.openerp.dao"> </property>
</bean>

어노테이션으로 bean을 자동으로 찾도록 했다.
jUnit 에서도 이 어노테이션을 가져올 수 있도록 지원하기 때문에 일일이 bean으로 서비스 클래스(테스트 대상)를 등록할 필요는 없다.

기타 설정은 패스...

UserServiceTest.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package com.openerp.service.test;
 
import java.util.Calendar;
import java.util.List;
import javax.annotation.Resource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Test;
import com.openerp.common.utils.JSONUtil;
import com.openerp.common.utils.Parameters;
import com.openerp.domain.User;
import com.openerp.service.UserService;
 
public class UserServiceTest extends AbstractApplicationContextTest{
    private static Log log = LogFactory.getLog(UserServiceTest.class);
     
    @Resource(name="userService")
    private UserService userService;
         
    @Test
    public void testSelectAllUser(){
        // 아래 Parameters는 그냥 Map으로 보시면 됨..
        Parameters<string, string=""> params = new Parameters<string, string="">();
        params.addValue("isDisable", "");
        List<user> users = userService.listUsers(params);
        // 아래 코드는 JSON 형식으로 바꿔주는 로직..
        System.out.println(JSONUtil.toJSON(users, null));
    }
}
</user></string,></string,>

어노테이션으로 등록된 UserService를 가지고 오기 위해 @Resource 어노테이션을 이용했다.
applicationContext.xml에 bean 태그를 이용해서 등록한 bean은 @Autowired가 가능하나, 어노테이션 검색으로 찾은 bean은 안되더라.
@Resource를 이용해서 검색하게 하니 정상적으로 작동을 한다...
지금 이 클래스는 UserService에 대한 테스트 인데 다른 Service에 대한 테스트도 해야 한다면 지금과 같이 AbstractApplicationContextTest 만 상속해서 사용을 하면 된다.
이는 각 서비스가 사용하는 설정(applicationContext)가 동일할 경우이고, 만약 각 업무별로 applicationContext을 나누어 사용한다면 AbstractApplicationContextTest 외에 다른 클래스를 만들어 상속해서 쓰면 된다.
(결론은 설정을 안쪼갰다면 하나의 슈퍼클래스에 설정을 밀어넣고 상속해서 사용한다는 것..)


jUnit 등 Test Case를 적용할 경우 편하긴 편하다.
서버(tomcat 등)를 재시작 할 필요도 없고, 코드만 고치고 해당 @Test 어노테이션이 붙은 메서드를 jUnit으로 실행만 하면 기존 방법(서버를 통한)과 동일한 결과를 이루어 낼 수 있다.
java, xml 코드 하나 고치고 빌드 -> 서버 재시작 -> 웹에서 액션 -> 결과 확인 무한 반복...
이제 이런걸 안하고도 서비스 클래스를 쉽게 작성할 수 있으니 개발 효율성이 향상되는 효과를 누릴 수 있다.