본문 바로가기
개발/테스트

Mockito) Unnecessary Stubbing Exception 해결

by 얼굴값하는사람 2024. 7. 4.
반응형

 

개요 

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

반응형