제육's 휘발성 코딩
article thumbnail
반응형

2.1 UserDaoTest 다시보기

public static void main(String[] args) throws SQLException, ClassNotFoundException {
  UserDao dao = new UserDao();

  User user = new User();
  user.setId("sasca");
  user.setName("jalgayo");
  user.setPassword("jalgayo");

  dao.add(user);
  System.out.println(user.getId() +" 등록 성공");

  User user2 = dao.get(user.getId());
  System.out.println(user2.getName());
  System.out.println(user2.getPassword());

  System.out.println(user2.getId() +" 조회 성공");

}

1장에서 만든 UserDao를 테스트하기 위한 테스트 코드를 만들었다.

테스트란 결국 내가 예상하고 의도했던 대로 코드가 정확히 동작하는지를 확인해서, 만든 코드를 확신할 수 있게 해주는 작업이다.

 

웹을 통한 DAO 테스트 방법의 문제점

웹 환경에서 DAO를 테스트하기 위해 서비스 계층, MVC 계층까지 모두 포함된 기능을 어느정도 구현하고 테스트를 한다.

DAO에 대한 테스트로는 너무 불필요한 수고가 필요하다. 이런 방식의 테스트는 번거롭고 대응하기 어려운 문제가 있다.

 

작은 단위의 테스트

테스트하고자 하는 대상이 명확하다면, 그 대상에 집중해서 테스트하는 것이 바람직하다.

이렇게 작은 단위의 코드에 대해 테스트를 수행한 것을 단위 테스트 라고 한다.

단위 테스트를 통해 main() 메서드가 아닌 Junit 테스트로 전환해보자.

 

2.2 UserDaoTest 개선

기존에 만들었던 main() 메서드 테스트는 프레임워크에 적용하기에 적합하지 않다.

IoC를 통해 제어권을 갖고 있는 것이 아닌, main() 메서드에 제어권을 갖고 있기 때문이다.

import static org.junit.Assert.assertThat;
import static org.hamcrest.CoreMatchers.is;
import java.sql.SQLException;
import org.junit.Test;
import org.junit.runner.JUnitCore;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;
import springbook.user.dao.UserDao;
import springbook.user.domain.User;


public class UserDaoTest {

  public static void main(String[] args) {
    JUnitCore.main("springbook.user.main.UserDaoTest");
  }

  @Test
  public void addAndGet() throws SQLException, ClassNotFoundException {
    ApplicationContext context = new GenericXmlApplicationContext("applicationContext.xml");
    UserDao dao = context.getBean("userDao", UserDao.class);
    User user = new User();
    user.setId("sasca37");
    user.setName("jalgayo");
    user.setPassword("jalgayo");

    dao.add(user);

    User user2 = dao.get(user.getId());

    assertThat(user2.getName(), is(user.getName()));
    assertThat(user2.getPassword(), is(user.getPassword()));
  }

}
  • 테스트가 성공한다면 Time과 OK 가 출력된다. 실패한다면, 실패한 원인과 위치에 대해서도 확인할 수 있다.
  • main 메서드로 JUnitCore.main를 실행시키지 않아도, 이클립스의 Run As 에 Junit Test를 실행하여 결과를 확인할 수 있다.

image

  • assertThat 검증에 실패한다면, 다음과 같이 실패 로그가 출력된다.

 

2.3 개발자를 위한 프레임워크 JUnit

JUnitCore를 이용해 테스트를 실행하고, 결과를 보는 것은 간단하지만, 테스트 수가 많아질수록 관리가 어려워진다. 따라서, IDE에서 제공하는 JUnit 테스트 지원 도구를 사용하는 것이 바람직하다.

image

  • JUnit 에는 @Before, @Test, @After 어노테이션이 있다.
  • 테스트 클래스에서 @Test가 붙고 파라미터가 없는 public void 형 테스트 메서드를 모두 찾아서 각 메서드별 독립적으로 실행하고, 결과 값을 반환해준다.

프로젝트 빌드를 위해 ANT나 Maven 같은 빌드 툴과 스크립트를 사요하고 있다면, 빌드 과정에서 JUnit을 실행할 수 있다.

 

2.3.2 테스트 결과의 일관성

매번 INSERT GET 하는 과정에서 PK 오류가 발생할 것이다. 가장 좋은 해결책은 테스트 등록한 사용자 정보를 삭제할 수 있는 로직을 만들어주는 것이다.

public void deleteAll() throws SQLException {
  Connection c = dataSource.getConnection();
  PreparedStatement ps = c.prepareStatement("delete from users");
  ps.executeUpdate();

  ps.close();
  c.close();
}

public int getCount() throws SQLException {
  Connection c = dataSource.getConnection();
  PreparedStatement ps = c.prepareStatement("select count(*) from users");

  ResultSet rs = ps.executeQuery();
  rs.next(); // 최초의 ResultSet은 1행 이전에 커서에 위치해있기 때문에 결과 반환을 위해 next() 메서드를 호출

  int count = rs.getInt(1);

  rs.close();
  ps.close();
  c.close();

  return count;
}
  • 다음과 같이 UserDao에 사용자 정보 전체 삭제, 갯수를 가져오는 로직을 만들어주자.
@Test
public void count() throws SQLException, ClassNotFoundException {
  ApplicationContext context = new GenericXmlApplicationContext("applicationContext.xml");
  UserDao dao = context.getBean("userDao", UserDao.class);

  User user1 = new User("test1", "a", "123");
  User user2 = new User("test2", "b", "123");
  User user3 = new User("test3", "c", "123");

  dao.deleteAll();
  assertThat(dao.getCount(), is(0));

  dao.add(user1);
  dao.add(user2);
  assertThat(dao.getCount(), is(2));

  User userget1 = dao.get(user1.getId());
  assertThat(userget1.getName(), is(user1.getName()));

  User userget2 = dao.get(user2.getId());
  assertThat(userget2.getName(), is(user2.getName()));
}
  • 세 개의 User 오브젝트로 테스트 정상여부를 확인해보자.

image

  • 다음과 같이 정상으로 출력된다. 여기서 주의할 점은 Junit은 특정한 테스트 메서드의 실행 순서를 보장해주지 않는다는 점이다. 따라서 테스트의 실행 순서에 영향을 받는다면 잘못 만든 테스트이다. 실행 순서와 상관 없이 독립적으로 동일한 결과를 낼 수 있도록 주의하자.
public User get(String id) throws ClassNotFoundException, SQLException {
  Connection c = dataSource.getConnection();
  PreparedStatement ps = c.prepareStatement("select * from users where id = ?");
  ps.setString(1, id);

  ResultSet rs = ps.executeQuery();
  rs.next();
  User user = new User();
  user.setId(rs.getString("id"));
  user.setName(rs.getString("name"));
  user.setPassword(rs.getString("password"));

  rs.close();
  ps.close();
  c.close();

  return user;
}
  • get 메서드를 살펴보면 User id 정보를 받아와서 해당 User 정보를 반환되도록 구현되어있다. 만약에 해당 Id가 없는 경우를 대비해, 예외 클래스를 지정하자. 스프링에는 EmptyResultDataAccessException 예외를 제공한다.
@Test(expected = EmptyResultDataAccessException.class)
public void getUserFailure() throws SQLException, ClassNotFoundException {
  ApplicationContext context = new GenericXmlApplicationContext("applicationContext.xml");

  UserDao dao = context.getBean("userDao", UserDao.class);
  dao.deleteAll();

  assertThat(dao.getCount(), is(0));

  dao.get("unknown_id");
}
  • expected를 통해 예외가 발생한다는 것을 검증해보자. 실행해보면 실패한다. 그 이유는 결과 값이 없는 상태에서 ResultSet에서 next를 호출하여 지정한 예외가 아닌, SQLException이 발생했기 때문이다.
public User get(String id) throws ClassNotFoundException, SQLException {
  Connection c = dataSource.getConnection();
  PreparedStatement ps = c.prepareStatement("select * from users where id = ?");
  ps.setString(1, id);

  ResultSet rs = ps.executeQuery();

  User user = null;
  if (rs.next()) { // 결과가 있으면 사용자 정보 생성
    user = new User();
    user.setId(rs.getString("id"));
    user.setName(rs.getString("name"));
    user.setPassword(rs.getString("password"));
  }
  rs.close();
  ps.close();
  c.close();

    if (user == null) throw new EmptyResultDataAccessException(1); // 예외 던지기
  return user;
}
  • 다음과 같이 결과가 있을 때 사용자정보를 반환하도록 처리해주면 테스트 결과가 정상으로 처리된다.

 

테스트 주도 개발

getUserFailure() 테스트에는 조건, 행위, 결과에 대한 내용이 잘 표현되어있다.

  • 조건 : 가져올 사용자 정보가 존재하지 않는 경우 생성
  • 행위 : 존재하지 않는 id로 get()을 실행
  • 결과 : 지정한 예외가 발생한다.

만들고자 하는 기능의 내용을 담고 있는 테스트 코드를 먼저 만들고, 테스트를 성공하도록 코드를 작성하는 개발 방식을 테스트 주도 개발 방식(TDD : Test Driven Development)이라고 한다.

TDD는 개발자가 테스트를 만들어가며 개발하는 방법이 주는 장점을 극대화한 방법이라고 볼 수 있다. 실패한 테스트를 성공시키기 위한 목적이 아닌 코드는 만들지 않는다는 것이 TDD의 기본 원칙이다.

 

2.3.5 테스트 코드 개선

지금까지 세 개의 테스트 메서드를 만들었다.

ApplicationContext context = new GenericXmlApplicationContext("applicationContext.xml");
UserDao dao = context.getBean("userDao", UserDao.class);
  • 세 개의 테스트 코드 모두 동일한 스프링 애플리케이션 컨텍스트의 빈 설정 정보를 가져오는 것이 눈에 띈다.

 

@Before

JUnit에는 @Test 를 실행하기 전, 필요한 내용을 실행해주는 @Before 어노테이션이 있다.

import java.sql.SQLException;

import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;
import org.springframework.dao.EmptyResultDataAccessException;

import springbook.user.dao.UserDao;
import springbook.user.domain.User;
import static org.junit.Assert.assertThat;
import static org.hamcrest.CoreMatchers.is;
public class UserDaoTest {

  private UserDao dao;

  @Before
  public void setUp() {
    ApplicationContext context = new GenericXmlApplicationContext("applicationContext.xml");
    this.dao = context.getBean("userDao", UserDao.class);
  }

  @Test
  public void addAndGet() throws SQLException, ClassNotFoundException {
    User user = new User();
    user.setId("sasca37");
    user.setName("jalgayo");
    user.setPassword("jalgayo");

    dao.add(user);

    User user2 = dao.get(user.getId());

    assertThat(user2.getName(), is(user.getName()));
    assertThat(user2.getPassword(), is(user.getPassword()));
  }

  @Test
  public void count() throws SQLException, ClassNotFoundException {
    User user1 = new User("test1", "a", "123");
    User user2 = new User("test2", "b", "123");
    User user3 = new User("test3", "c", "123");

    dao.deleteAll();
    assertThat(dao.getCount(), is(0));

    dao.add(user1);
    dao.add(user2);
    assertThat(dao.getCount(), is(2));

    User userget1 = dao.get(user1.getId());
    assertThat(userget1.getName(), is(user1.getName()));

    User userget2 = dao.get(user2.getId());
    assertThat(userget2.getName(), is(user2.getName()));
  }

  @Test(expected = EmptyResultDataAccessException.class)
  public void getUserFailure() throws SQLException, ClassNotFoundException {
    dao.deleteAll();

    assertThat(dao.getCount(), is(0));

    dao.get("unknown_id");
  }
}
  • 애플리케이션 컨텍스트 빈 정보를 가져오는 것을 @Before 어노테이션을 통해 간략화 할 수 있다.

 

픽스처

테스트를 수행하는 데 필요한 정보나 오브젝트를 픽스처(fixture)라고 한다. 일반적으로 픽스처는 여러 테스트에서 반복적으로 사용되기 때문에 @Before 메서드를 이용해 생성해두면 편리하다.

private UserDao dao;
private User user1;
private User user2;
private User user3;

@Before
public void setUp() {
  ApplicationContext context = new GenericXmlApplicationContext("applicationContext.xml");
  this.dao = context.getBean("userDao", UserDao.class);
  this.user1 = new User("test1", "a", "123");
  this.user2 = new User("test2", "b", "123");
  this.user3 = new User("test3", "c", "123");
}
  • User 픽스처를 사용하면 매번 새로운 오브젝트가 만들어지도록 구현되어 인스턴스 변수에 바로 초기화 해도 상관이 없다. 따라서, 테스트 메서드 별로 편리하게 사용할 수 있다.

 

2.4 스프링 테스트 적용

아직 한 가지 찜찜한 부분이 남아 있다. 바로 애플리케이션 컨텍스트 생성 방식이 @Before 메서드를 통해 메서드 갯수 만큼 반복되어 생성되고 있다는 점이다. 빈이 많아지고 복잡해지면, 컨텍스트 생성 비용도 만만치 않게 된다.

테스트는 가능한 독립적으로 매번 새로운 오브젝트를 만들어서 사용하는 것이 원칙이다. 하지만, 애플리케이션 컨텍스트처럼 생성에 많은 시간과 자원이 소모되는 경우, 테스트 전체가 공유하는 오브젝트를 만들기도 한다. 또한, 빈은 싱글톤으로 만들었기 때문에 한번 초기화되고 나면 내부의 상태가 바뀌지 않는다.

JUnit은 매번 테스트 클래스의 오브젝트를 만들기 때문에 전체에 걸쳐 딱 한 번만 실행되는 @BeforeClass 스태틱 메서드를 지원한다.

2.4.1 테스트를 위한 애플리케이션 컨텍스트 관리

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>3.0.7.RELEASE</version>
        <scope>test</scope>
    </dependency>
  • 스프링에서 지원하는 테스트를 사용하기 위해 다음과 같이 spring-test 라이브러리를 등록하자.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
                           http://www.springframework.org/schema/beans/spring-beans.xsd">

  <bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
    <property name="driverClass" value="com.mysql.cj.jdbc.Driver"></property>
    <property name="url" value="jdbc:mysql://localhost/tobi"></property>
    <property name="username" value=""></property>
    <property name="password" value=""></property>
  </bean>

  <bean id="userDao" class="springbook.user.dao.UserDao">
    <property name="dataSource" ref="dataSource" />     
  </bean>
</beans>
  • applicationContext.xml (src/main/resources)
@RunWith(SpringJUnit4ClassRunner.class) // 스프링 테스트 컨텍스트 프레임워크의 JUnit 확장 가능지정 
@ContextConfiguration(locations = "/applicationContext.xml") // 테스트 컨텍스트가 자동으로 만들어줄 애플리케이션 컨텍스트 지정
public class UserDaoTest {

  @Autowired
  private ApplicationContext context;

  private UserDao dao;
  private User user1;
  private User user2;
  private User user3;

  @Before
  public void setUp() {
    this.dao = this.context.getBean("userDao", UserDao.class);
    this.user1 = new User("test1", "a", "123");
    this.user2 = new User("test2", "b", "123");
    this.user3 = new User("test3", "c", "123");
  }
  • spring-test 라이브러리를 통해 애클리케이션 컨텍스트를 최초 한번 초기화하도록 사용할 수 있다.
  • @Autowired 를 통해 테스트 컨텍스트 프레임워크는 일치하는 컨텍스트 내의 빈을 찾아 주입해준다. 일반적으로 생성자나 세터 주입이 필요하지만, 이 경우에는 메서드 없이도 주입이 가능하다. 이러한 방법을 자동와이어링이라고 한다. (애플리케이션 컨텍스트는 초기화할 때 자기 자신도 빈으로 등록하고 그 빈을 DI 받은 셈)

context는 어디에서도 초기화 해주는 코드가 없다. NPE 발생이 예상되지만, 실제론 정상으로 통과된다. 즉, 초기화 하지 않은 context에 애플리케이션 컨텍스트가 들어가있다. 이는 @Runwith 어노테이션에 SpringJUnit4Class.Runner 클래스를 지정해주면, JUnit이 테스트를 진행하는 중에 테스트가 사용할 애플리케이션 컨텍스트를 만들고 관리하는 작업을 진행해주기 때문이다. (일종의 DI라고 볼 수 있다.)

 

테스트 클래스의 컨텍스트 공유

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "/applicationContext.xml")
public class UserDaoTest {}

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "/applicationContext.xml")
public class GroupDaoTest {}
  • 스프링 테스트 컨텍스트 프레임워크 기능은, 여러 개의 테스트 클래스에도 같은 설정파일이면 애플리케이션 컨텍스트 간 공유를 할 수 있다. 즉, 단 하나의 애플리케이션 컨텍스트만 만들어서 사용할 수 있다.

 

@Autowired 을 통해 DL 방식을 DI로 전환하기

private UserDao dao;

@Before
public void setUp() {
  this.dao = this.context.getBean("userDao", UserDao.class); // DL (Dependency Lookup)
  this.user1 = new User("test1", "a", "123");
  this.user2 = new User("test2", "b", "123");
  this.user3 = new User("test3", "c", "123");
}
  • 현재의 코드는 DI 받아온 애플리케이션 컨텍스트를 다시 빈 저장소를 명시하는 DL 방식으로 UserDao의 빈 정보를 가져오고 있다.
@Autowired
private UserDao dao;

@Before
public void setUp() {
  //this.dao = this.context.getBean("userDao", UserDao.class);
}
  • @Autowired를 활용하여, DI 방식을 통해 코드를 깔끔히 처리할 수 있다.

 

테스트와 운영 환경 분리

만약 이 애플리케이션을 운영환경에 둔다고 가정하면, 현재의 UserDao의 코드는 어떻게 될까?

deleteAll 메서드 테스트로 인해 모두 삭제되는 위험한 가능성에 있다, 그렇다고 해서 프로필 별로 DataSource 오브젝트를 바꿔주는 방법을 사용하기엔 불편하다.

 

수동 DI 적용 @DirtiesContext

@RunWith(SpringJUnit4ClassRunner.class) // 스프링 테스트 컨텍스트 프레임워크의 JUnit 확장 가능지정 
@ContextConfiguration(locations = "/applicationContext.xml")
@DirtiesContext // 테스트 메서드에서 애플리케이션 컨텍스트의 구성이나 상태를 변경한다는 것을 명시
public class UserDaoTest {

  @Autowired
  private ApplicationContext context;

  @Autowired
  private UserDao dao;
  private User user1;
  private User user2;
  private User user3;

  @Before
  public void setUp() {
    DataSource dataSource = new SingleConnectionDataSource("jdbc:mysql://localhost/test", "", "", true); //test 용 db 스키마 입력
    dao.setDataSource(dataSource); // setter 주입
    this.user1 = new User("test1", "a", "123");
    this.user2 = new User("test2", "b", "123");
    this.user3 = new User("test3", "c", "123");
  }
  • 스프링에서 제공하는 DataSource인 SingleConnectionDataSource를 사용해서 커넥션을 연결하자.
  • 이전의 설명에서 애플리케이션 컨텍스트는 한 번만 초기화 된다고 했었다. DataSource 의존 관계를 강제로 변경한 상황에서 나머지 모든 테스트 또한 변경된 애플리케이션 컨텍스트 정보를 사용할 것이다. 이 때 @DirtiesContext 사용을 통해 해당 클래스의 테스트에서만 애플리케이션 컨텍스트의 상태를 변경함을 알려줄 수 있다. 단, 매번 애플리케이션 컨텍스트를 만들기 때문에 불편한 점이 있다.

@DirtiesContext는 메서드레벨에서도 적용이 가능하다. 지정한 메서드의 실행이 끝나고 이후에 진행되는 테스트를 위해 새로운 애플리케이션 컨텍스트가 만들어진다.

이러한 불안전한 환경보다는, test용 XML 파일을 새로 만들어 테스트 클래스에 적용하는 것이 바람직하다고 생각한다.

 

컨테이너 없는 DI 테스트

이번에는 스프링 컨테이너 사용 없이 DI 테스트를 해보자.

//@Autowired
private UserDao dao; 
private User user1;
private User user2;
private User user3;

@Before
public void setUp() {
  dao = new UserDao();
  DataSource dataSource = new SingleConnectionDataSource("jdbc:mysql://localhost/tobi", "root", "", true);
  dao.setDataSource(dataSource);
  this.user1 = new User("test1", "a", "123");
  this.user2 = new User("test2", "b", "123");
  this.user3 = new User("test3", "c", "123");
}
  • UserDao가 스프링 API에 의존하지 않고 깔끔하게 테스트를 통과할 수 있다.

JUnit 테스트 오브젝트 테스트

JUnit은 테스트 메서드를 수행할 때 마다 새로운 오브젝트를 만든다고 했다.

JUnit과 스프링 테스트에서 자신에 대한 러닝 테스트를 해보자.

Junit 테스트 오브젝트

import org.hamcrest.CoreMatchers;
import org.hamcrest.core.Is;
import org.junit.Assert;
import org.junit.Test;

import static org.hamcrest.CoreMatchers.*;
import static org.junit.matchers.JUnitMatchers.hasItem;
import java.util.HashSet;
import java.util.Set;

public class JUnitTest {
  static JUnitTest testObject;
  static Set<JUnitTest> testObjects = new HashSet<>(); // 테스트 오브젝트를 저장할 컬렉션 생성

  @Test
  public void test1() {
    Assert.assertThat(testObjects, not(hasItem(this))); // 같지 않아야 성공
    testObjects.add(this); // 자기 자신 추가
  }

  @Test
  public void test2() {
    Assert.assertThat(testObjects, not(hasItem(this)));
    testObjects.add(this);
  }

  @Test
  public void test3() {
    Assert.assertThat(testObjects, not(hasItem(this)));
    testObjects.add(this);
  }
}
  • 테스트의 순서와 상관 없이 오브젝트 중복 여부를 테스트해보았을 때 정상 결과를 반환한다. 즉, 메서드 마다 새로운 클래스 오브젝트를 만드는 것을 검증했다.

스프링 테스트 오브젝트

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
  • 스프링 테스트를 위한 빈 설정파일을 생성하자 같은 패키지 안에 생성하자.
import org.junit.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;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.matchers.JUnitMatchers.either;
import static org.junit.matchers.JUnitMatchers.hasItem;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/junit.xml")
public class SpringJUnitTest {

  @Autowired
  ApplicationContext context;

  static Set<SpringJUnitTest> testObjects = new HashSet<>();
  static ApplicationContext contextObject = null;


  @Test
  public void test1() {
    assertThat(testObjects, not(hasItem(this)));
    testObjects.add(this);

    assertThat(contextObject == null || contextObject == this.context, is(true));
    contextObject = this.context;
  }

  @Test
  public void test2() {
    assertThat(testObjects, not(hasItem(this)));
    testObjects.add(this);

    assertTrue(contextObject == null || contextObject == this.context);
    contextObject = this.context;
  }

  // @Test 
  public void test3() {
    assertThat(testObjects, not(hasItem(this)));
    testObjects.add(this);
    assertThat(contextObject, either(is(nullValue())).or(is(this.context)));
    contextObject = this.context;
  }
}
  • 테스트 메서드에서 매번 동일한 애플리케이션 컨텍스트가 context 변수에 주입됐는 지 확인해야 한다. 각 테스트별 동일한 기능이나, either 테스트는 현재 실패로 나오는데, 원인이 파악되면 추후 정리해두려고 한다.

2.6 정리

  • 테스트는 코드의 변경 없이 환경이나 테스트 실행 순서에 따라 결과가 달라지면 안된다.
  • 테스트는 자동화돼야 하고, 빠르게 실행할 수 있어야한다.
  • @Before, @After 어노테이션으로 공통 작업을 처리할 수 있다.
  • 스프링 테스트에서 @Autowired를 사용하면 컨텍스트의 빈을 테스트 오브젝트에 DI할 수 있다.
  • 테스트 클래스에서 @Test가 붙고 파라미터가 없는 public void 형 테스트 메서드를 모두 찾아서 각 메서드별 독립적으로 실행하고, 결과 값을 반환해준다.
  • 동일한 설정파일을 사용하는 테스트는 하나의 애플리케이션 컨텍스트를 공유한다.

REFERENCE

  • 토비의 스프링 3.1
반응형
profile

제육's 휘발성 코딩

@sasca37

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요! 맞구독은 언제나 환영입니다^^