import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
public class ProviderLoginTest {
@Mock
private UserRepository userRepository;
@Mock
private SecurityService securityService;
@Mock
private ProviderService providerService;
@Test
public void testLoginProvider() {
// Test code goes here
}
}
@Mock 어노테이션이 UserRepository와 SecurityService 인스턴스를 생성하고, @InjectMocks 어노테이션은 이러한 Mock 객체를 ProviderService 인스턴스에 주입합니다.
이로 인해, 테스트를 수행하는 동안 UserRepository와 SecurityService는 Mock 인스턴스가 되고, 이들의 동작은 Mockito를 통해 제어됩니다.
이렇게 설정한 후에는 이전에 작성했던 Mockito.when()과 같은 호출로 Mock 객체의 동작을 설정할 수 있습니다.
@Mock
와 @InjectMocks
는 Mockito에서 제공하는 어노테이션이며, 둘 간에는 명확한 차이점이 있습니다.
@Mock
은 간단히 말해 테스트에서 사용할 모의 객체(mock object)를 생성하는 데 사용됩니다. 이렇게 생성된 모의 객체는 실제 객체와 동일한 API를 가지지만, 그 동작은 개발자가 테스트 내에서 제어합니다. 이는 특정 메소드의 결과를 테스트하거나, 특정 메소드가 호출되었는지 검증하는 등의 용도로 사용됩니다.
그러나 @Mock
으로 생성된 객체는 모의 객체이므로 그 안에 있는 의존성들은 채워지지 않습니다. 즉, @Mock
으로 생성한 ProviderService
객체는 내부에서 사용하는 UserRepository
나 SecurityService
등의 의존성이 주입되지 않습니다.
반면에, @InjectMocks
는 Mockito가 @Mock
이나 @Spy
어노테이션이 붙은 객체를 해당 객체의 필드로 주입(inject)해줍니다. 즉, @InjectMocks
를 사용하면 ProviderService의 내부 의존성인 UserRepository와 SecurityService에 @Mock
으로 생성한 모의 객체가 주입되어, 실제 코드와 유사한 상황에서 테스트를 진행할 수 있게 됩니다.
따라서, 당신이 질문에서 언급한 @Mock ProviderService providerService;
코드에서 ProviderService
는 모의 객체지만, 그 안의 UserRepository
나 SecurityService
는 null
일 것입니다. 이 코드가 "동작"한다는 것은, ProviderService
객체가 성공적으로 생성되었으며 그 메소드를 호출할 수 있음을 의미하지만, 그 메소드 내부에서 UserRepository
나 SecurityService
를 사용하려고 하면 NullPointerException이 발생할 것입니다.
만약 ProviderService
의 메소드가 UserRepository
나 SecurityService
를 사용하지 않는다면, @Mock ProviderService providerService;
코드만으로도 테스트가 잘 수행될 수 있습니다. 그러나 일반적으로 서비스 계층의 메소드는 내부의 다른 컴포넌트들을 사용하기 때문에, 대부분의 경우 @InjectMocks
를 사용해야 합니다.
예를들면
@InjectMocks
를 사용하는 것은 테스트하고자 하는 클래스가 다른 클래스를 의존하고 있고, 이를 모의 객체로 대체하여 테스트하고 싶을 때 사용합니다.
예를 들어, ProviderService
클래스가 UserRepository
와 SecurityService
를 사용하고 있고 이들을 테스트에서는 모의 객체로 사용하고 싶다면, 다음과 같이 사용합니다:
@Mock
private UserRepository userRepository;
@Mock
private SecurityService securityService;
@InjectMocks
private ProviderService providerService;
이렇게 하면, ProviderService
에 대한 테스트에서는 UserRepository
와 SecurityService
가 @Mock
으로 선언된 모의 객체로 대체되어 사용됩니다.
반대로 SecurityService
클래스가 ProviderService
를 사용하고 있고, 이를 모의 객체로 대체하여 SecurityService
의 테스트를 하고 싶다면 다음과 같이 사용할 수 있습니다:
@Mock
private ProviderService providerService;
@InjectMocks
private SecurityService securityService;
이렇게 하면, SecurityService
의 테스트에서 ProviderService
는 @Mock
으로 선언된 모의 객체로 대체되어 사용됩니다.
즉, @InjectMocks
를 사용하는 클래스는 테스트 대상 클래스이며, 그 클래스가 사용하는 다른 클래스들은 @Mock
이나 @Spy
로 선언하여 모의 객체로 사용하게 됩니다. 이렇게 하면, 테스트 대상 클래스를 다른 클래스로부터 독립적으로 테스트할 수 있습니다.