상세 컨텐츠

본문 제목

[6.2] 고립된 단위 테스트

토비의스프링

by kwanghyup 2020. 11. 2. 17:48

본문

 

UserDao를 인터페이스로 만들고 

기존의 UserDao는 UserDaoJdbc로 이름을 바꾸었다. 

 

 

#고립된 단위 테스트 활용 

 

UserServcieTest의 upgradeLevels()테스트에 적용해보자

 

MockUserDao

package springbook.user.dao;

import java.util.ArrayList;
import java.util.List;

import springbook.user.domain.User;

public class MockUserDao implements UserDao{
	
	// 레벨 업그레이드 후보 목록 User 오브젝트
	private List<User> users; 
	
	// 업그레이드 대상 오브젝트를 저장해둘 목록 
	private List<User> updated = new ArrayList<User>();

	public MockUserDao(List<User> users) {
		this.users = users;
	}
	
	public List<User> getUpdated(){
		return this.updated;
	}
	
	// 스텁 기능 제공
	@Override
	public List<User> getAll(){
		return this.users;
	}
	
	// 목 오브젝트 기능 제공 
	@Override
	public void update(User user) {
		updated.add(user);
	}

	
	// 사용하지 않는 메소드는 UnsupportedOperationException 예외를 던진다.
	@Override
	public void add(User user) {throw new UnsupportedOperationException(); }

	@Override
	public User get(String id) {throw new UnsupportedOperationException();}

	@Override
	public void deleteAll() {throw new UnsupportedOperationException();}

	@Override
	public int getCount() {throw new UnsupportedOperationException();}
	
}

 

이제 upgradeLevels()테스트가 MockUserDao를 사용하도록 수정하자.

@Test
public void upgradeLevels() throws Exception {
	//고립된 테스트에서는 테스트 대상 오브젝트를 직접 생성하면된다.
	UserServiceImpl userServiceImpl = new UserServiceImpl();
	
	//목 오브젝트로 만든 UserDao를 직접 DI해준다.
	MockUserDao mockUserDao = new MockUserDao(this.users);
	userServiceImpl.setUserDao(mockUserDao);
	
	MockMailSender mockMailSender = new MockMailSender();
	userServiceImpl.setMailSender(mockMailSender);
	
	userServiceImpl.upgradeLevels();
	
	//MockUserDao로부터 업데이트된 결과를 가져온다. 
	List<User> updated = mockUserDao.getUpdated();
	assertEquals(updated.size(), 2);
	checkUserAndLevel(updated.get(0), "joytouch", Level.SILVER);
	checkUserAndLevel(updated.get(1), "madnite1", Level.GOLD);
	
	
	List<String> request = mockMailSender.getReuests();
	assertEquals(request.size(), 2);
	assertEquals(request.get(0), users.get(1).getEmail());
	assertEquals(request.get(1), users.get(3).getEmail());
}

// id와 level을 확인하는 메소드 
private void checkUserAndLevel(User updated, String expectedId, Level expectedLevel) {
	assertEquals(updated.getId(), expectedId);
	assertEquals(updated.getLevel(), expectedLevel);
}

 

# Mokito 프레임워크 

 

pom.xml

<!-- https://mvnrepository.com/artifact/org.mockito/mockito-all -->
<dependency>
	<groupId>org.mockito</groupId>
	<artifactId>mockito-all</artifactId>
	<version>1.10.19</version>
</dependency>

 

UserDao 인터페이스를 구현한 테스트용 목 오브젝트는 

다음과 같이 Mockito의 스태틱 메소드를 한 번 호출해주면 만들어진다. 

import static org.mockito.Mockito.mock;
//...
UserDao mockUserDao = mock(UserDao.class);

 

다음은 mockUserDao.getAll()이 호출됐을때 users리스트를 리턴해주라는 선언이다.

when(mockUserDao.getAll()).thenReturn(this.users);

 

mockUserDao의 update()메소드가 두 번 호출됐는지 확인하고 싶다면

다음과 같은 검증코드를 넣어주면된다.

verify(mockUserDao, times(2)).update(any(User.class));
//User타입의 오브젝트를 파라미터로 받는 update()메소드가 2번 호출됐는지 확인하라는 것이다.

 

Mockito를 적용한 테스트 코드 

//...

import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

//...

@Test
public void upgradeLevels() throws Exception {
	UserServiceImpl userServiceImpl = new UserServiceImpl();
	
	UserDao mockUserDao = mock(UserDao.class);
	when(mockUserDao.getAll()).thenReturn(this.users);
	userServiceImpl.setUserDao(mockUserDao);
	
	MailSender mockMailSender = mock(MailSender.class);
	userServiceImpl.setMailSender(mockMailSender);
	
	userServiceImpl.upgradeLevels();
	
	//레벨 검증 
	verify(mockUserDao, times(2)).update(any(User.class));
	verify(mockUserDao).update(users.get(1));
	assertEquals(users.get(1).getLevel(), Level.SILVER);
	verify(mockUserDao).update(users.get(3));
	assertEquals(users.get(3).getLevel(), Level.GOLD);
	
	ArgumentCaptor<SimpleMailMessage> mailMessageArg = 
			ArgumentCaptor.forClass(SimpleMailMessage.class);
	verify(mockMailSender, times(2)).send(mailMessageArg.capture());
	List<SimpleMailMessage> mailMessages = mailMessageArg.getAllValues();
	assertEquals(mailMessages.get(0).getTo()[0], users.get(1).getEmail());
	assertEquals(mailMessages.get(1).getTo()[0], users.get(3).getEmail());
}

 MailSender의 경우는 ArgumentCaptor라는 것을 사용해서 

실제 MailSender 목 오브젝트에 전달된 파라미터를 가져와 

내용을 검증하는 방법을 사용했다.

 

파라미터를 직접 비교하기 보다는 파라미터의 내부 정보를 확인해야 하는 경우에 유용하다.

관련글 더보기

댓글 영역