스프링

토비의 스프링 - 2.4 스프링 테스트 적용

초롱불 2021. 5. 30. 21:45

개요

1. 중복 코드 정리

2. 스프링 테스트 적용

3. DI와 테스트

본문

1. 중복 코드 정리

중복 코드 정리는 사실 이전 페이지에서 다루었어야 했는데 건드리지 않고 넘어갔기에 이번 페이지에서 다루겠다. UserDaoTest의 메소드를 살펴보면 중복되는 코드를 발견할 수 있다. 이를 @Before라는 애너테이션을 통해서 먼저 선언 하고 사용하거나, 오브젝트를 픽스처로 선언함으로써 중복을 제거할 수 있다. 아래의 코드를 살펴보면 바로 이해할 수 있을 것이다.

public class UserDaoTest {
	
	private UserDao dao;//setup() 메소드에서 만드는 오브젝트를 테스트 메소드에서 사용할 수 있도록 인스턴스 변수로 선언
	private User user1; //주로 사용하는 오브젝트 픽스처 적용
	private User user2;
	private User user3;

	
	@Before //JUnit이 제공하는 애노테이션, @Test 메소드가 실행되기 전에 먼저 실행돼야 하는 메소드를 정의한다.
	public void setUp() {
		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml", UserDao.class);
		this.dao = context.getBean("userDao", UserDao.class);
		this.user1 = new User("cho1", "초롱불1", "greenligh1");
		this.user2 = new User("cho2", "초롱불2", "greenligh2");
		this.user3 = new User("cho3", "초롱불3", "greenligh3");
	}

	 //Junit에게 테스트 메소드임을 알려줌
	@Test
	public void addAndGet() throws SQLException {//테스트 메소드는 반드시 public으로 선언
																		
		//테스트에서 반복되는 부분 @Before로 추출
		//ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml", UserDao.class);
		//UserDao dao = context.getBean("userDao", UserDao.class);
		
		dao.deleteAll();//테이블 비우기
		assertThat(dao.getCount(), is(0));//0개인지 체크, 아니면 오류 메세지 출력

		User user = new User("cho", "초롱불", "greenlight");
		
		dao.add(user);
		assertThat(dao.getCount(), is(1));//1개인지 체크, 아니면 오류 메세지 출력


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

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

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

	}
	
	@Test
	public void count() throws SQLException {//테스트 메소드는 반드시 public으로 선언
		
		//테스트에서 반복되는 부분 @Before로 추출
		//ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml", UserDao.class);
		//UserDao dao = context.getBean("userDao", UserDao.class);

//		User user1 = new User("cho1", "초롱불1", "greenligh1");
//		User user2 = new User("cho2", "초롱불2", "greenligh2");
//		User user3 = new User("cho3", "초롱불3", "greenligh3"); 픽스처를 적용
		
		dao.deleteAll();
		assertThat(dao.getCount(), is(0));
		
		dao.add(user1);
		assertThat(dao.getCount(), is(1));

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


	}
	
	
	@Test(expected=EmptyResultDataAccessException.class)
	public void getUserFailure() throws SQLException {
		//테스트에서 반복되는 부분 @Before로 추출
		//ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml", UserDao.class);
		//UserDao dao = context.getBean("userDao", UserDao.class);
		
		dao.deleteAll();
		assertThat(dao.getCount(), is(0));
		
		dao.get("unknown_id");
	}
	
}

2. 스프링 테스트 적용

위의 코드에서 애플리케이션 컨텍스트의 생성은 @Before메소드가 반복될 때마다 이루어진다. 매 메소드 마다 새로운 애플리케이션 컨텍스트가 생성되는 것이다. 이것은 무수히 많은 메소드의 테스트가 이루어 질 수도 있음을 가정하면 극히 비효율적이다. 스프링이 제공하는 애플리케이션 컨텍스트 테스트 지원 기능을 이용한다면 이 문제를 해결할 수 있다. 적용을 위해서는 아래와 같이 수정하면 된다.

@RunWith(SpringJUnit4ClassRunner.class)//스프링-테스트 프레임워크의 JUnit 확장기능 지정
@ContextConfiguration(locations="/springbook/user/test3/dao/applicationContext.xml")//테스트 컨텍스트가 자동으로 만들어줄 애플리케이션 컨텍스트 위치 지정
public class UserDaoTest {
	
	@Autowired
	private ApplicationContext context; //테스트 오브젝트가 만들어지고 나면 스프링 테스트 컨텍스트에 의해 자동으로 값 주입
	...

	
	@Before //JUnit이 제공하는 애노테이션, @Test 메소드가 실행되기 전에 먼저 실행돼야 하는 메소드를 정의한다.
	public void setUp() {
    	System.out.println(this.context); //컨텍스트 체크 - 컨텍스트는 한 번만 만들어진다
		System.out.println(this); //오브젝트 값 체크 - 오브젝트는 매번 만들어진다
		this.dao = context.getBean("userDao", UserDao.class);
		...
	}
  

context와 테스트 오브젝트 자신(this)를 출력한 값

정말로 컨텍스트가 매번 다르게 생성되지 않고 한 번 생성한 뒤 그대로 유지되며 사용하는지도 확인하기 위해서 중간에 System.out.println(this.context); 와 System.out.println(this)를 끼워넣어 체크를 해보았다. context는 @5ad851c9값으로 중복되어서 값이 나오고 테스트 오브젝트(this)는 그 값이 다양하게 나오는 것을 확인해볼 수 있다.

3. DI와 테스트

@Autowired는 DI에 사용되는 애너테이션이다. @Autowired로 선언된 context는 초기화 하지 않아도 null이 아닌 그 값을 가지는 것을 확인할 수 있다. Autowired는 애플리케이션 컨텍스트 내의 빈을 찾아서 자동으로 변수에 주입해준다. 애플리케이션 컨텍스트 그 자체는 xml에서 정의된 빈이라고 할 수는 없지만 그 자신도 빈으로 등록하게끔 설정되어 있기에 위와 같은 Autowired도 가능해진다. 당연히 문서상 bean으로 등록되어 있는 UserDao도 DI로 받을 수 있다. 

정리

1. 중복 코드를 @Before와 픽스처를 이용해서 줄일 수 있다.

2. 스프링에서 지원해주는 테스트 기능을 이용하면 애플리케이션 컨텍스트를 한 번만 생성하고 효율적으로 활용가능하다.

3. @Autowired는 Bean의 DI를 가능하게 한다.

소스 깃허브

 

https://github.com/cholongbul/Tobyspring

 

cholongbul/Tobyspring

토비의 스프링 연습. Contribute to cholongbul/Tobyspring development by creating an account on GitHub.

github.com