JUnit x Spring 에서 이어짐
package org.edwith.webbe.calculatorcli;
import org.springframework.stereotype.Service;
@Service
public class MyService {
// MyService 클래스는 CalculatorSerivce를 필드로 갖는다.
private final CalculatorService calculatorService;
public MyService(CalculatorService calculatorService) {
this.calculatorService = calculatorService;
}
public int execute(int value1, int value2) {
return calculatorService.plus(value1, value2) * 2;
}
}
package org.edwith.webbe.calculatorcli;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/* @RunWith(SpringJUnit4ClassRunner.class)
* : JUnit이 테스트 코드를 실행할 때 Spring Bean 컨테이너가 내부적으로 생성되도록 한다.
*
* @ContextConfiguration(classes = {ApplicationConfig.class})
* : 내부적으로 생성된 Spring Bean 컨테이너가 사용할 설정파일을 지정할 때 사용한다.
*
* class 위의 두 어노테이션으로 인해 테스트 클래스 자체가 Bean 객체가 되어 Spring에서 관리하게 된다.
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {ApplicationConfig.class})
public class MyServiceTest {
/* MyServiceTest 클래스가 Bean으로 관리되면서,
* Spring Bean 컨테이너는 Bean들을 찾아 메모리에 올리고
* MyService 필드에 객체를 주입할 수 있게 된다.(@Autowired)
*/
@Autowired
MyService myService;
@Test
public void execute() throws Exception{
// given
int value1 = 5;
int value2 = 10;
// when
int result = myService.execute(value1, value2);
// then
Assert.assertEquals(30, result);
}
}
만약 관계맺은 CalculatorSerivce의 plus() 메서드가 버그, 오류가 있다면 어떻게 될까?
-> 내가 생각한 값이 나오지 않을 것이다.
MySerivce가 사용하던 CalculatorService를 사용하는 대신, 가짜 객체를 하나 생성한다. 내가 원하는 동작을 Mock 객체로 CalculatorService를 사용함으로써 MyService의 내용만 테스트를 수행할 수 있다.
...
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>1.9.5</version>
<scope>test</scope>
</dependency>
...
package org.edwith.webbe.calculatorcli;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import static org.mockito.BDDMockito.given;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.verify;
@RunWith(MockitoJUnitRunner.class)
public class MyServiceTest {
// Mock 객체를 사용하는 MyService 객체를 생성하여 초기화하라는 의미
@InjectMocks
MyService myService;
// calculatorService가 Mock 객체를 참조하도록 한다.
// 자동으로 객체가 생성되고 해당 필드가 초기화 된다는 것을 의미
@Mock
CalculatorService calculatorService; // 가짜 객체
@Test
public void execute() throws Exception{
// given
int value1 = 5;
int value2 = 10;
// given 메서드 : 가짜 객체가 동작하는 방법을 규정
given(calculatorService.plus(5, 10)).willReturn(15);
// when
int result = myService.execute(value1, value2);
// then
// verify 메소드 : 파라미터로 들어온 객체의 plus메소드가 호출된 적이 있는지 검증
// 이 상황에서는 어떤 정수든지 2개를 파라미터로 넣어서 plus()메소드를 호출했는지를 검증
verify(calculatorService).plus(anyInt(), anyInt());
Assert.assertEquals(30, result);
}
}
결과