Injecting Mockito Mocks into Spring Beans

Dev.Hammy·2024년 4월 1일

Mockito_Tutorial

목록 보기
16/21

1. Overview

이 튜토리얼에서는 단위 테스트를 위해 Spring Bean에 Mockito 모의 객체를 삽입하기 위해 종속성 주입을 사용하는 방법에 대해 설명합니다.

구성 요소가 외부 시스템 액세스에 의존하는 경우가 많은 실제 애플리케이션에서는 적절한 테스트 격리를 제공하여 각 테스트에 전체 클래스 계층 구조를 포함하지 않고도 특정 장치의 기능을 테스트하는 데 집중할 수 있도록 하는 것이 중요합니다.

모의 객체를 주입하는 것은 이러한 격리를 도입하는 깔끔한 방법입니다.

2. Maven Dependencies

단위 테스트와 모의 객체에는 다음과 같은 Maven 종속성이 필요합니다.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>2.21.0</version>
</dependency>

이 예에서는 Spring Boot를 사용하기로 결정했지만 클래식 Spring도 잘 작동합니다.

3. Writing the Test

3.1 The Business Logic

먼저 테스트할 간단한 서비스를 만들어 보겠습니다.

@Service
public class NameService {
    public String getUserName(String id) {
        return "Real user name";
    }
}

그런 다음 이를 UserService 클래스에 삽입합니다.

@Service
public class UserService {

    private NameService nameService;

    @Autowired
    public UserService(NameService nameService) {
        this.nameService = nameService;
    }

    public String getUserName(String id) {
        return nameService.getUserName(id);
    }
}

이 문서의 경우 제공된 클래스는 제공된 ID에 관계없이 단일 이름을 반환합니다. 이는 복잡한 논리를 테스트하는 데 주의가 산만해지지 않도록 하기 위한 것입니다.

또한 빈을 스캔하고 애플리케이션을 초기화하려면 표준 Spring Boot 메인 클래스가 필요합니다.

@SpringBootApplication
public class MocksApplication {
    public static void main(String[] args) {
        SpringApplication.run(MocksApplication.class, args);
    }
}

3.2 The Tests

이제는 노력해야 합니다. 우선, 테스트를 위해 필요한 사항을 구성해야 합니다.

@Profile("test")
@Configuration
public class NameServiceTestConfiguration {
    @Bean
    @Primary
    public NameService nameService() {
        return Mockito.mock(NameService.class);
    }
}

@Profile 어노테이션은 "test" 프로필이 활성화된 경우에만 이 구성을 적용하도록 Spring에 지시합니다. @Primary 어노테이션은 autowiring을 위해 실제 인스턴스 대신 이 인스턴스가 사용되는지 확인하기 위해 존재합니다. 메소드 자체는 NameService 클래스의 Mockito 모형을 생성하고 반환합니다.

이제 단위 테스트를 작성할 수 있습니다.

@ActiveProfiles("test")
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = MocksApplication.class)
public class UserServiceUnitTest {

    @Autowired
    private UserService userService;

    @Autowired
    private NameService nameService;

    @Test
    public void whenUserIdIsProvided_thenRetrievedNameIsCorrect() {
        Mockito.when(nameService.getUserName("SomeId")).thenReturn("Mock user name");
        String testName = userService.getUserName("SomeId");
        Assert.assertEquals("Mock user name", testName);
    }
}

@ActiveProfiles 어노테이션을 사용하여 "test" 프로필을 활성화하고 이전에 작성한 모의 구성을 활성화합니다. 결과적으로 Spring은 UserService 클래스의 실제 인스턴스를 자동 연결하지만 NameService 클래스의 모의 인스턴스를 자동 연결합니다. 테스트 자체는 상당히 일반적인 JUnit+Mockito 테스트입니다. 우리는 원하는 모의 동작을 구성한 다음 테스트하려는 메서드를 호출하고 우리가 기대하는 값을 반환한다고 주장합니다.

이러한 테스트에서 환경 프로필을 사용하지 않는 것도 가능합니다(권장되지는 않지만). 이를 위해 @Profile@ActiveProfiles 어노테이션을 제거하고 UserServiceTest 클래스에 @ContextConfiguration(classes = NameServiceTestConfiguration.class) 어노테이션을 추가합니다.

0개의 댓글