java&spring

H2 DB와 JUnit을 사용하여 테스트

sungjine 2017. 4. 14. 22:37
반응형

JUnit Test를 진행하는데 실제 DB에 있는 데이터를 건들지 않고 테스트를 하고 싶은 마음에 시작한 프로젝트이다. 연습하는 김에 Java로 설정해 보았다.

 

먼저 Gradle로 라이브러리를 빌드하자

 

build.gradle

compile group: 'org.springframework', name: 'spring-context', version: '4.3.7.RELEASE'
compile group: 'commons-dbcp', name: 'commons-dbcp', version: '1.2.2'
compile group: 'org.springframework', name: 'spring-jdbc', version: '4.3.7.RELEASE'
compile group: 'org.mybatis', name: 'mybatis-spring', version: '1.2.1'
compile group: 'org.mybatis', name: 'mybatis', version: '3.1.1'
compile group: 'com.h2database', name: 'h2', version: '1.4.192'
testCompile group: 'org.springframework', name: 'spring-test', version: '4.3.7.RELEASE'
testCompile group: 'junit', name: 'junit', version: '4.+'

 

그다음에는 Java Code로 설정해보자

 

AppConfig.java

@Configuration
public class AppConfig {
    @Autowired
    private ApplicationContext applicationContext;
     
    @Bean
    public UserDao userDao(SqlSession session) {
        return new UserDao(session);
    }
     
    @Bean
    public DataSource dataSource(){
        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriverClassName("org.h2.Driver");
        dataSource.setUrl("jdbc:h2:mem:testdb;INIT=RUNSCRIPT FROM 'classpath:init.sql'");
        dataSource.setUsername("sa");
        dataSource.setPassword("");
         
        return dataSource;
    }
     
    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
     
    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
        sessionFactory.setMapperLocations(applicationContext.getResources("classpath:sql/*.xml"));
        return (SqlSessionFactory)sessionFactory.getObject();
    }
     
    @Bean
    public SqlSession session(SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

 

설정중 H2 DB를 사용하기 위해서 dataSource는 BasicDataSource 클래스로 만들어야 한다. (이것 때문에 1시간을 넘게 소비해서 작성해놓는다)

 

transactionManager 메소드는 Test Code에서 Transaction 어노테이션을 사용하기 위해 작성한다.

 

그리고 위 코드는 각 메소드에 파라미터를 넣어 줬는데 넣지 않고 아래 코드와 같이 그냥 메소드를 사용해도 된다. 단 throws 되는 Exception 들을 계속 throws 해줘야 한다.

 

AppConfig.session()

@Bean
public SqlSession session() throws Exception {
    return new SqlSessionTemplate(sqlSessionFactory());
}

 

테스트를 위한 설정은 모두 끝났다. 이제 Dao를 만들어 보자.

 

UserDao.java

@Repository
public class UserDao {
     
    @Autowired
    private SqlSession session;
     
    public UserDao(SqlSession session){
        this.session = session;
    }
     
    public UserVo findUserById(long id){
        return session.selectOne("findUserById", id);
    }
     
    public List<UserVo> findAllUsers(){
        return session.selectList("findAllUsers");
    }
     
    public void insertUser(UserVo user){
        session.insert("insertUser", user);
    }
     
    public void updateUser(UserVo user){
        session.update("updateUser", user);
    }
}

 

Dao에는 두 가지 Select 메소드와 Insert, Update 메소드가 하나씩 있다.

 

그다음 UserVo이다.

 

UserVo.java

public class UserVo {
    private long id;
    private String name;
    private String email;
    private String password;
     
    public UserVo(){}
    public UserVo(long id, String name, String email, String password){
        this.id = id;
        this.name = name;
        this.email = email;
        this.password = password;
    }
    public UserVo(String name, String email, String password){
        this.name = name;
        this.email = email;
        this.password = password;
    }
 
    public long getId() {
        return id;
    }
    public void setId(long id) {
        this.id = id;
    }
    public UserVo(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public void setName(String name) {
        this.name = name;
    }
     
    public String toString(){
        return "id : " + id + ", name : " + name + ", email : " + email + ", password : " + password;
    }
}

 

테스트를 진행하기에 앞서 query문을 작성하자

첫번째는 테스트를 진행하기 전에 만들어질 테이블과 데이터를 입력한 query문이다.

 

init.sql

DROP TABLE IF EXISTS users;
 
CREATE TABLE users (
    id INT(20) NOT NULL AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(10) NOT NULL,
    email VARCHAR(20),
    password VARCHAR(20)
);
 
INSERT INTO users(name, email, password) VALUES('testName', 'testEmail@test.com', 'testPassword');

 

두번째는 CRUD를 진행할 query문이다.

 

sql/userSql.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="userVo">
    <select id="findUserById" resultType="org.gradle.vo.UserVo" parameterType="java.lang.Long">
        SELECT id, name, email, password FROM users WHERE id = #{id}
    </select>
 
    <select id="findAllUsers" resultType="org.gradle.vo.UserVo">
        SELECT id, name, email, password FROM users
    </select>
 
    <insert id="insertUser" parameterType="org.gradle.vo.UserVo">
        INSERT INTO users (name, email, password)
        VALUES (#{name}, #{email}, #{password})
    </insert>
 
    <update id="updateUser" parameterType="org.gradle.vo.UserVo">
        UPDATE users SET
            name = #{name},
            email = #{email},
            password = #{password}
        WHERE ID = #{id}
    </update>
</mapper>

 

이제 테스트를 진행해보자

 

UserDaoTest.java

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader=AnnotationConfigContextLoader.class,classes={AppConfig.class})
public class UserDaoTest {
     
    @Autowired
    private UserDao userDao;
     
    @Test
    @Transactional
    public void findUserByIdTest(){
        UserVo user = userDao.findUserById(1L);
        assertEquals("testName", user.getName());
        assertEquals("testEmail@test.com", user.getEmail());
        assertEquals("testPassword", user.getPassword());
    }
     
    @Test
    @Transactional
    public void findAllUsersest(){
        List<UserVo> users = userDao.findAllUsers();
        assertEquals(1, users.size());
        UserVo user = users.get(0);
        assertEquals("testName", user.getName());
        assertEquals("testEmail@test.com", user.getEmail());
        assertEquals("testPassword", user.getPassword());
    }
     
    @Test
    @Transactional
    public void insertUserTest(){
        List<UserVo> users = userDao.findAllUsers();
        assertEquals(1, users.size());
        UserVo inser = new UserVo("name", "email", "password");
        userDao.insertUser(inser);
        users = userDao.findAllUsers();
        assertEquals(2, users.size());
        UserVo user = users.get(1);
        assertEquals("name", user.getName());
        assertEquals("email", user.getEmail());
        assertEquals("password", user.getPassword());
    }
     
    @Test
    @Transactional
    public void updateUserTest(){
        UserVo user = userDao.findUserById(1L);
        assertEquals("testName", user.getName());
        assertEquals("testEmail@test.com", user.getEmail());
        assertEquals("testPassword", user.getPassword());
        userDao.updateUser(new UserVo(1L, "name", "email", "password"));
        user = userDao.findUserById(1L);
        assertEquals("name", user.getName());
        assertEquals("email", user.getEmail());
        assertEquals("password", user.getPassword());
    }
}

 

모든 코드를 작성했다. 이제 테스트를 해보는 것만 남았다.

 

typeAlias를 사용 하기위한 코드를 추가해보자

 

먼저 AppConfig 클래스에 있는 sqlSessionFactory() 메소드에 sessionFactory.setTypeAliasesPackage("org.gradle.vo");를 추가하자 그다음 UserVo 클래스 상단에 @Alias("userVo")을 붙여주고 userSql.xml 파일에서 org.gradle.vo.UserVo로 작성한 것들을 userVo로 수정해주면 된다.

반응형