Mock을 만들 때는 세가지 방법을 쓸 수 있다.
@Test
public void givenCountMethodMocked_WhenCountInvoked_ThenMockedValueReturned() {
UserRepository localMockRepository = Mockito.mock(UserRepository.class);
Mockito.when(localMockRepository.count()).thenReturn(111L);
long userCount = localMockRepository.count();
Assert.assertEquals(111L, userCount);
Mockito.verify(localMockRepository).count();
}
이 Mockito는 무슨 라이브러리일까?
Mockito is a mocking framework for Java. Mockito allows convenient creation of substitutes of real objects for testing purposes. Enjoy clean tests with mock objects, improved TDD experience and beautiful mocking API. See the main page or examples for more.
Mockito는 테스트를 목적으로 실제 객체의 대용품을 만들어준다.
혹은 Mockito의 @Mock 어노테이션을 쓰면 된다.
@RunWith(MockitoJUnitRunner.class)
public class MockAnnotationUnitTest {
@Mock
UserRepository mockRepository;
@Test
public void givenCountMethodMocked_WhenCountInvoked_ThenMockValueReturned() {
Mockito.when(mockRepository.count()).thenReturn(123L);
long userCount = mockRepository.count();
Assert.assertEquals(123L, userCount);
Mockito.verify(mockRepository).count();
}
}
스프링의 @MockBean을 쓸 수도 있다.
@RunWith(SpringRunner.class)
public class ExampleTests {
@MockBean
private ExampleService service;
@Autowired
private UserOfService userOfService;
@Test
public void testUserOfService() {
given(this.service.greet()).willReturn("Hello");
String actual = this.userOfService.makeUse();
assertEquals("Was: Hello", actual);
}
@Configuration
@Import(UserOfService.class) // A @Component injected with ExampleService
static class Config {
}
}
Unit tests are designed to test a component in isolation from other components and unit tests have also a requirement : being as fast as possible in terms of execution time as these tests may be executed each day dozen times on the developer machines.
유닛테스트는 보통 다른 컴포넌트와는 분리된 상태에서 진행돼야 하며, 빠른 속도로 진행돼야 한다.
As you write a test that doesn't need any dependencies from the Spring Boot container, the classic/plain Mockito is the way to follow : it is fast and favors the isolation of the tested component.
If your test needs to rely on the Spring Boot container and you want also to add or mock one of the container beans : @MockBean from Spring Boot is the way.
스프링 부트의 다른 의존성이 필요하지 않다면 일반적인 Mocktio를 쓰면 되고, 그렇지 않다면 @Mockbean을 쓰면 된다고 한다.
참고로 @Mockbean은 deprecate돼서 @MockitoBean을 쓰면 된다고 한다.
아래처럼 사용하면 된다.
@RunWith(SpringRunner.class)
public class ExampleTests {
@MockBean
private ExampleService service;
@Autowired
private UserOfService userOfService;
@Test
public void testUserOfService() {
given(this.service.greet()).willReturn("Hello");
String actual = this.userOfService.makeUse();
assertEquals("Was: Hello", actual);
}
@Configuration
@Import(UserOfService.class) // A @Component injected with ExampleService
static class Config {
}
}
@MocktioBean 어노테이션을 등록하면 Spring ApplicationContext에 mock을 등록해준다.
이 mock은 타입이나 이름으로 등록될 수 있는데, 타입으로 등록되면 이 타입에 대응하는 싱글톤 빈이 mock으로 대체된다.
자세한 사용법은 공식문서에 나와있으니 참고하자.
현재 스프링 버전이 낮아서 @MocktioBean은 쓰지 못한다.
이렇게 @Mockbean을 붙여준다.
@BeforeEach
void setUp() {
userGenerator.generateWithRole("fnel123", "123", "dd", "연호", TOP, HUNTER);
file = new MockMultipartFile(
"file",
"test.jpg",
"image/jpeg",
new byte[0] // 빈 파일
);
when(s3ImagesServiceV1.uploadImages(anyList())).thenReturn(
List.of(new SavedImage("test.jpg", true)));
verify(s3ImagesServiceV1).uploadImages(anyList()); //1번 호출됏는지 검증하는게 디폴트값이다.
}
그리고, Mutlipart(사진파일)도 mock으로 만들어놓고, mock이 반환할 데이터도 미리 지정해둔다.