Loading...
Spring Framework Reference Documentation 7.0.2의 @MockitoBean and @MockitoSpyBean의 한국어 번역본입니다.
아래의 경우에 피드백에서 신고해주신다면 반영하겠습니다.
감사합니다 :)
@MockitoBean and @MockitoSpyBean@MockitoBean과
@MockitoSpyBean은
테스트의 ApplicationContext에서 bean을 Mockito mock 또는 _spy_로 각각 오버라이드하기 위해
테스트 클래스에서 사용할 수 있습니다. 후자의 경우, 원래 bean의 초기 인스턴스가 캡처되어 spy로
감싸집니다.
이 어노테이션들은 다음과 같은 방식으로 적용될 수 있습니다.
@Nested 테스트 클래스의 enclosing 클래스 또는 @Nested 테스트 클래스 위의 타입 계층이나
enclosing 클래스 계층에 있는 어떤 클래스의 non-static 필드에 적용.@Nested 테스트 클래스의 enclosing 클래스 또는 @Nested 테스트 클래스 위의 타입 계층이나
enclosing 클래스 계층에 있는 어떤 클래스나 인터페이스의 타입 레벨에 적용.@MockitoBean 또는 @MockitoSpyBean이 필드에 선언되면, mock 또는 spy할 bean은
어노테이션이 달린 필드의 타입으로부터 유추됩니다. 해당하는 candidate가 ApplicationContext에
여러 개 존재하는 경우, 필드에 @Qualifier 어노테이션을 선언하여 모호성을 해소할 수 있습니다.
@Qualifier 어노테이션이 없는 경우, 어노테이션이 달린 필드의 이름이 _fallback qualifier_로
사용됩니다. 또는, 어노테이션에서 value 또는 name 속성을 설정하여 mock 또는 spy할
bean 이름을 명시적으로 지정할 수도 있습니다.
@MockitoBean 또는 @MockitoSpyBean이 타입 레벨에 선언되는 경우, mock 또는 spy할 bean
타입(또는 bean들)은 어노테이션의 types 속성을 통해 제공되어야 합니다. 예를 들어,
@MockitoBean(types = {OrderService.class, UserService.class})와 같습니다.
ApplicationContext에 여러 candidate가 존재하는 경우, name 속성을 설정하여 mock 또는
spy할 bean 이름을 명시적으로 지정할 수 있습니다. 단, 명시적인 bean name이 설정된 경우
types 속성에는 하나의 타입만 포함되어야 합니다. 예를 들어,
@MockitoBean(name = "ps1", types = PrintingService.class)와 같습니다.
mock 설정의 재사용을 지원하기 위해, @MockitoBean과 @MockitoSpyBean은
메타어노테이션으로 사용되어 custom _composed annotations_를 생성할 수 있습니다. 예를 들어,
테스트 스위트 전체에서 재사용할 수 있는 공통 mock 또는 spy 설정을 하나의 어노테이션에
정의할 수 있습니다. @MockitoBean과 @MockitoSpyBean은 타입 레벨에서 repeatable
어노테이션으로도 사용할 수 있습니다. 예를 들어, 이름으로 여러 bean을 mock 또는 spy하기 위해
사용할 수 있습니다.
필드 이름을 포함한 qualifier들은 별도의
ApplicationContext가 생성되어야 하는지를 결정하기 위해 사용됩니다. 여러 테스트 클래스에서 동일한 bean을 mock 또는 spy하기 위해 이 기능을 사용하는 경우, 불필요한 컨텍스트 생성을 피하기 위해 필드 이름을 일관되게 지정해야 합니다.
@MockitoBean또는@MockitoSpyBean을@ContextHierarchy와 함께 사용하면, 각@MockitoBean또는@MockitoSpyBean이 기본적으로 모든 컨텍스트 계층 레벨에 적용되기 때문에 바람직하지 않은 결과를 초래할 수 있습니다. 특정@MockitoBean또는@MockitoSpyBean이 하나의 컨텍스트 계층 레벨에만 적용되도록 보장하려면,contextName속성을 설정하여 구성된@ContextConfiguration이름과 일치시키십시오. 예를 들어,@MockitoBean(contextName = "app-config")또는@MockitoSpyBean(contextName = "app-config")와 같이 설정합니다. 자세한 내용과 예제는 context hierarchies with bean overrides를 참조하십시오.
각 어노테이션은 또한 mocking 동작을 미세 조정하기 위한 Mockito 전용 속성들을 정의합니다.
@MockitoBean 어노테이션은 strategy for bean overrides로
REPLACE_OR_CREATE를 사용합니다.
해당하는 bean이 존재하지 않으면, 새로운 bean이 생성됩니다. 그러나,
enforceOverride 속성을 true로 설정하여 REPLACE 전략으로 전환할 수 있습니다.
예를 들어, @MockitoBean(enforceOverride = true)와 같습니다.
@MockitoSpyBean 어노테이션은 strategy로
WRAP을 사용하며, 원래 인스턴스는 Mockito spy로 감싸집니다. 이 전략은 candidate bean이
정확히 하나만 존재해야 합니다.
Mockito 문서에서 설명된 바와 같이, spy에 대한 stubbing에
Mockito.when()을 사용하는 것이 부적절한 경우가 있습니다. 예를 들어, spy에서 실제 메서드를 호출하면 원치 않는 부작용이 발생하는 경우입니다. 이러한 원치 않는 부작용을 피하기 위해,Mockito.doReturn(…).when(spy)…,Mockito.doThrow(…).when(spy)…,Mockito.doNothing().when(spy)…및 이와 유사한 메서드들의 사용을 고려하십시오.
@MockitoBean을 사용하여 non-singleton bean을 mock하는 경우, non-singleton bean은 싱글톤 mock으로 대체되며, 해당 bean 정의는singleton으로 변환됩니다. 따라서prototype또는 스코프드 bean을 mock하는 경우, 해당 mock은singleton으로 취급됩니다. 마찬가지로,@MockitoSpyBean을 사용하여 non-singleton bean에 대한 spy를 생성하는 경우, 해당 bean 정의는singleton으로 변환됩니다. 따라서prototype또는 스코프드 bean에 대한 spy를 생성하는 경우, 해당 spy는singleton으로 취급됩니다.@MockitoBean을 사용하여FactoryBean에 의해 생성되는 bean을 mock하는 경우,FactoryBean은FactoryBean이 생성하는 객체 타입의 싱글톤 mock으로 대체됩니다. 마찬가지로,@MockitoSpyBean을 사용하여FactoryBean에 대한 spy를 생성하는 경우, spy는FactoryBean자체가 아니라FactoryBean이 생성하는 객체에 대해 생성됩니다. 또한,@MockitoSpyBean은 스코프드 프록시에 대해 spy하는 데 사용할 수 없습니다. 예를 들어,@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)로 어노테이션된 bean이 이에 해당합니다. 이렇게 시도하는 경우 예외와 함께 실패합니다.
@MockitoBean및@MockitoSpyBean필드의 가시성에는 아무런 제한이 없습니다. 따라서 이러한 필드는 프로젝트의 요구 사항이나 코딩 관행에 따라public,protected, package-private(default visibility) 또는private가 될 수 있습니다.
@MockitoBean Examples다음 예제는 @MockitoBean 어노테이션의 기본 동작을 사용하는 방법을 보여줍니다.
1@SpringJUnitConfig(TestConfig.class) 2class BeanOverrideTests { 3 4 @MockitoBean // (1) 5 CustomService customService; 6 7 // tests... 8}
| 1 | CustomService 타입의 bean을 Mockito mock으로 대체합니다. |
위 예제에서는 CustomService에 대한 mock을 생성합니다. 해당 타입의 bean이 둘 이상 존재하는
경우, customService라는 이름의 bean이 고려됩니다. 그렇지 않으면 테스트가 실패하며,
오버라이드하려는 CustomService bean을 식별하기 위해 어떤 형태로든 qualifier를 제공해야
합니다. 해당 bean이 전혀 존재하지 않는 경우, 자동 생성된 bean 이름을 사용하여 bean이
생성됩니다.
다음 예제는 by-type 조회가 아니라 by-name 조회를 사용합니다. service라는 이름의 bean이
존재하지 않으면 하나가 생성됩니다.
1@SpringJUnitConfig(TestConfig.class) 2class BeanOverrideTests { 3 4 @MockitoBean("service") // (1) 5 CustomService customService; 6 7 // tests... 8 9}
| 1 | service라는 이름의 bean을 Mockito mock으로 대체합니다. |
다음 @SharedMocks 어노테이션은 두 개의 mock을 by-type으로, 하나의 mock을 by-name으로
등록합니다.
1@Target(ElementType.TYPE) 2@Retention(RetentionPolicy.RUNTIME) 3@MockitoBean(types = {OrderService.class, UserService.class}) // (1) 4@MockitoBean(name = "ps1", types = PrintingService.class) // (2) 5public @interface SharedMocks { 6}
| 1 | OrderService와 UserService mock을 by-type으로 등록합니다. |
| 2 | PrintingService mock을 by-name으로 등록합니다. |
다음은 테스트 클래스에서 @SharedMocks를 사용하는 방법을 보여줍니다.
1@SpringJUnitConfig(TestConfig.class) 2@SharedMocks // (1) 3class BeanOverrideTests { 4 5 @Autowired OrderService orderService; // (2) 6 7 @Autowired UserService userService; // (2) 8 9 @Autowired PrintingService ps1; // (2) 10 11 // Inject other components that rely on the mocks. 12 13 @Test 14 void testThatDependsOnMocks() { 15 // ... 16 } 17}
| 1 | custom @SharedMocks 어노테이션을 통해 공통 mock을 등록합니다. |
| 2 | mock을 stub 또는 _verify_하기 위해 선택적으로 주입합니다. |
mock은 또한 Mockito의 stubbing API로 구성하기 위해
ApplicationContext내의@Configuration클래스나 다른 테스트 관련 컴포넌트에 주입될 수 있습니다.
@MockitoSpyBean Examples다음 예제는 @MockitoSpyBean 어노테이션의 기본 동작을 사용하는 방법을 보여줍니다.
1@SpringJUnitConfig(TestConfig.class) 2class BeanOverrideTests { 3 4 @MockitoSpyBean // (1) 5 CustomService customService; 6 7 // tests... 8}
| 1 | CustomService 타입의 bean을 Mockito spy로 감쌉니다. |
위 예제에서는 CustomService 타입의 bean을 감싸고 있습니다. 해당 타입의 bean이 둘 이상
존재하는 경우, customService라는 이름의 bean이 고려됩니다. 그렇지 않으면 테스트가 실패하며,
spy하려는 CustomService bean을 식별하기 위해 어떤 형태로든 qualifier를 제공해야 합니다.
다음 예제는 by-type 조회가 아니라 by-name 조회를 사용합니다.
1@SpringJUnitConfig(TestConfig.class) 2class BeanOverrideTests { 3 4 @MockitoSpyBean("service") // (1) 5 CustomService customService; 6 7 // tests... 8}
| 1 | service라는 이름의 bean을 Mockito spy로 감쌉니다. |
다음 @SharedSpies 어노테이션은 두 개의 spy를 by-type으로, 하나의 spy를 by-name으로
등록합니다.
1@Target(ElementType.TYPE) 2@Retention(RetentionPolicy.RUNTIME) 3@MockitoSpyBean(types = {OrderService.class, UserService.class}) // (1) 4@MockitoSpyBean(name = "ps1", types = PrintingService.class) // (2) 5public @interface SharedSpies { 6}
| 1 | OrderService와 UserService spy를 by-type으로 등록합니다. |
| 2 | PrintingService spy를 by-name으로 등록합니다. |
다음은 테스트 클래스에서 @SharedSpies를 사용하는 방법을 보여줍니다.
1@SpringJUnitConfig(TestConfig.class) 2@SharedSpies // (1) 3class BeanOverrideTests { 4 5 @Autowired OrderService orderService; // (2) 6 7 @Autowired UserService userService; // (2) 8 9 @Autowired PrintingService ps1; // (2) 10 11 // Inject other components that rely on the spies. 12 13 @Test 14 void testThatDependsOnMocks() { 15 // ... 16 } 17}
| 1 | custom @SharedSpies 어노테이션을 통해 공통 spy를 등록합니다. |
| 2 | spy를 stub 또는 _verify_하기 위해 선택적으로 주입합니다. |
spy는 또한 Mockito의 stubbing API로 구성하기 위해
ApplicationContext내의@Configuration클래스나 다른 테스트 관련 컴포넌트에 주입될 수 있습니다.
@TestBean
@DirtiesContext