Mockito를 사용하면 테스트를 진행할 때, 외부 의존성을 가진 객체를 Mocking하여 테스트를 진행할 수 있다.
이번 포스팅에서는 Mockito를 사용하여 테스트를 진행하는 방법을 정리해보겠다.
✅ Mocking이란?
- Mocking은 테스트를 진행할 때, 외부 의존성을 가진 객체를 Mocking하여 테스트를 진행하는 방법이다.
- 실게 객체를 대신하는 가짜 객체를 생성하여 테스트를 진행할 수 있다.
- Mocking을 사용하면 외부 의존성을 가진 객체를 테스트할 때, 외부 의존성을 가진 객체의 행동을 제어할 수 있다.
- 예를 들어, 외부 의존성을 가진 객체의 메서드를 호출하면 예외를 발생시키거나, 특정 값을 반환하도록 설정할 수 있다.
✅ Mockito란?
- Mockito는 Mocking을 위한 Java 라이브러리이다.
- Mockito를 사용하면 테스트를 진행할 때, 외부 의존성을 가진 객체를 Mocking하여 테스트를 진행할 수 있다.
- Mockito는 Mocking을 위한 다양한 기능을 제공하며, 테스트를 진행할 때, 외부 의존성을 가진 객체의 행동을 제어할 수 있다.
- Mockito를 사용하면 외부 의존성을 가진 객체의 메서드를 호출하면 예외를 발생시키거나, 특정 값을 반환하도록 설정할 수 있다.
✅ Stub이란?
- Stubbing은 특정 메서드 호출시 반환될 값을 미리 지정 하는 것이다.
- 테스트를 진행할 때, 외부 의존성을 가진 객체의 행동을 제어할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
@Test
public void test() {
// given
when(mockObject.method()).thenReturn("mock"); // Stubbing
// when
String result = mockObject.method();
// then
assertThat(result).isEqualTo("mock");
}
위 예제에서 when(mockObject.method()).thenReturn("mock");
코드는 mockObject.method()
메서드가 호출될 때, “mock” 값을 반환하도록 설정한 것이다.
✅ Mocking을 위한 어노테이션
Mockito를 사용하여 테스트를 진행할 때, Mocking을 위한 어노테이션을 사용할 수 있다.
Mocking을 위한 어노테이션은 다음과 같다.
@Mock
: mock 객체를 만든다.@MockBean
: @SpringBootTest를 사용하면 ApplicationContext에 빈을 모두 등록하는데, 이 어노테이션을 붙이면 실제 빈 대신 mock 객체를 등록한다.@Spy
: 진짜 객체이며, 메서드 실행시 stubbing을 하지 않으면 기존 객체의 로직을, stubbing을 하면 stubbing된 값이 반환된다.@InjectMocks
: DI를 @Mock이나 @Spy로 생성된 mock 객체를 자동으로 주입해주는 어노테이션이다.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
@ExtendWith(MockitoExtension.class) class MockTest { @Mock private MockObject mockObject; @Spy private SpyObject spyObject; @Test public void test() { when(mockObject.method()).thenReturn("mock"); // Stubbing when(spyObject.method()).thenReturn("spy"); // Stubbing spyObject.method(); // 진짜 객체의 로직 실행 } }
✅ Verify란?
mock 객체의 메서드 호출을 검증하는 기능이다.
verify(T mock, VerificationMode mode)
메소드 명 | 설명 |
---|---|
times(n) | 몇 번이 호출됐는지 |
never | 한 번도 호출되지 않았는지 |
atLeastOne | 최소 한 번은 호출됐는지 |
atLeast(n) | 최소 n번이 호출됐는지 |
atMostOnce | 최대 한 번은 호출됐는지 |
atMost(n) | 최대 n번이 호출됐는지 |
calls(n) | n번이 호출됐는지 |
timeout(long mills) | n ms 이상 걸리면 fail |
after(long mills) | timeout과 달리 n ms 지나도 검증 종료되지 않음 |
description | 실패한 경우 나올 문구 |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@Test
public void example(){
Person p = mock(Person.class);
String name = "JDM";
p.setName(name);
// n번 호출했는지 체크
verify(p, times(1)).setName(any(String.class)); // success
// 호출 안했는지 체크
verify(p, never()).getName(); // success
verify(p, never()).setName(eq("ETC")); // success
verify(p, never()).setName(eq("JDM")); // fail
// 최소한 1번 이상 호출했는지 체크
verify(p, atLeastOnce()).setName(any(String.class)); // success
// 2번 이하 호출 했는지 체크
verify(p, atMost(2)).setName(any(String.class)); // success
// 2번 이상 호출 했는지 체크
verify(p, atLeast(2)).setName(any(String.class)); // fail
// 지정된 시간(millis)안으로 메소드를 호출 했는지 체크
verify(p, timeout(100)).setName(any(String.class)); // success
// 지정된 시간(millis)안으로 1번 이상 메소드를 호출 했는지 체크
verify(p, timeout(100).atLeast(1)).setName(any(String.class)); // success
}
마치며
mock의 핵심은 결국 아래와 같이 정리할 수 있을 것 같다.
mock
객체를 만든다.stub
으로 특정 메서드 호출시 반환될 값을 미리 지정한다.verify
로 mock 객체의 메서드 호출을 검증한다.- 테스트를 진행할 때, 외부 의존성을 가진 객체의 행동을 제어할 수 있다.