개요
Mockito를 사용한 테스트 케이스 실행시에 발생 할 수 있는 예외 입니다.
이번에는 UnnecessaryStubbingException이 발생하는 이유와 이를 해결하는 방법을 정리하려 합니다.
UnnecessaryStubbingException 의 발생 원인
Mocking 객체의 메서드가 실제로 테스트에서 사용되지 않았을 때 발생하는 예외입니다. 쉽게 말해, 테스트 코드에서 설정한 스텁(Stub)이 불필요하게 남아 있을 때 발생 합니다.
개발에 익숙하신 분이라면 아래 예제코드 없이 결론만 봐주세요
정공법적인 글이고 시간이 없으시다면 Mockito.lenient() 를 검색해주세요.
예제 코드
public class MyService {
private final MyRepository myRepository;
public MyService(MyRepository myRepository) {
this.myRepository = myRepository;
}
public String process() {
return myRepository.getData();
}
}
public interface MyRepository {
String getData();
}
위와 같은 코드에서 MyService 클래스는 MyRepository 인터페이스를 의존하고 있습니다. 이 때, 단위 테스트를 작성해 보겠습니다.
잘못된 테스트 코드
@RunWith(MockitoJUnitRunner.class)
public class MyServiceTest {
@Mock
private MyRepository myRepository;
@InjectMocks
private MyService myService;
@Test
public void testProcess() {
// UnnecessaryStubbingException 발생
when(myRepository.getData()).thenReturn("data");
// 실제 테스트에서는 getData() 메서드를 호출하지 않음
String result = myService.process();
}
}
위의 코드에서 when(myRepository.getData()).thenReturn("data"); 구문은 테스트에서 사용되지 않았기 때문에 UnnecessaryStubbingException이 발생합니다.
해결 방법
불필요한 스텁 제거
가장 간단한 방법은 테스트에서 실제로 사용되지 않는 스텁을 제거하는 것입니다.
@RunWith(MockitoJUnitRunner.class)
public class MyServiceTest {
@Mock
private MyRepository myRepository;
@InjectMocks
private MyService myService;
@Test
public void testProcess() {
// 필요 없는 스텁 제거
String result = myService.process();
}
}
Mockito 설정 변경
Mockito 설정을 변경하여 불필요한 스텁에 대해 예외를 발생시키지 않도록 할 수 있습니다. 이를 위해 MockitoJUnitRunner 대신 MockitoJUnit.rule()을 사용하고, strictness를 설정합니다.
public class MyServiceTest {
@Rule
public MockitoRule rule = MockitoJUnit.rule().strictness(Strictness.LENIENT);
@Mock
private MyRepository myRepository;
@InjectMocks
private MyService myService;
@Test
public void testProcess() {
when(myRepository.getData()).thenReturn("data");
String result = myService.process();
}
}
실제로 스텁 사용
또 다른 방법은 스텁을 실제 테스트에서 사용하는 것입니다.
@RunWith(MockitoJUnitRunner.class)
public class MyServiceTest {
@Mock
private MyRepository myRepository;
@InjectMocks
private MyService myService;
@Test
public void testProcess() {
when(myRepository.getData()).thenReturn("data");
// 스텁 사용
String result = myService.process();
assertEquals("data", result);
}
}
결론
Mockito의 UnnecessaryStubbingException은 테스트 코드에서 실제로 사용되지 않는 스텁이 있을 때 발생하는 예외입니다. 이를 해결하기 위해 불필요한 스텁을 제거하거나, Mockito 설정을 변경하거나, 스텁을 실제 테스트에서 사용하는 방법을 고려할 수 있습니다. 이를 통해 단위 테스트의 품질을 높이고, 유지보수성을 개선할 수 있습니다.
테스트 코드를 작성할 때 항상 필요한 스텁만을 사용하고, 불필요한 설정을 피하도록 주의하는 것이 중요합니다. 이렇게 하면 UnnecessaryStubbingException을 예방하고 더 나은 테스트 코드를 작성할 수 있습니다.
하지만... 쉽지 않네요. 반복만이 살길 입니다. ㅎ
참고자료
https://www.baeldung.com/mockito-unnecessary-stubbing-exception
https://stackoverflow.com/questions/42947613/how-to-resolve-unneccessary-stubbing-exception