복붙노트

[SPRING] @ComponentScan을 Spring의 테스트 특정 컨텍스트 구성과 함께 사용하는 방법 Junit4 TestRunner?

SPRING

@ComponentScan을 Spring의 테스트 특정 컨텍스트 구성과 함께 사용하는 방법 Junit4 TestRunner?

Spring Boot 애플리케이션을 테스트하고있다. 몇 가지 테스트 클래스가 있는데, 각각은 조롱 된 또는 다른 방식으로 사용자 정의 된 빈 집합이 필요합니다.

다음은 설정에 대한 스케치입니다.

src / main / java :

package com.example.myapp;

@SpringBootApplication
@ComponentScan(
        basePackageClasses = {
                MyApplication.class,
                ImportantConfigurationFromSomeLibrary.class,
                ImportantConfigurationFromAnotherLibrary.class})
@EnableFeignClients
@EnableHystrix
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

package com.example.myapp.feature1;

@Component
public class Component1 {
    @Autowired
    ServiceClient serviceClient;

    @Autowired
    SpringDataJpaRepository dbRepository;

    @Autowired
    ThingFromSomeLibrary importantThingIDontWantToExplicitlyConstructInTests;

    // methods I want to test...
}

src / test / java :

package com.example.myapp;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = MyApplication.class)
@WebAppConfiguration
@ActiveProfiles("test")
public class Component1TestWithFakeCommunication {

    @Autowired
    Component1 component1; // <-- the thing we're testing. wants the above mock implementations of beans wired into it.

    @Autowired
    ServiceClient mockedServiceClient;

    @Configuration
    static class ContextConfiguration {
        @Bean
        @Primary
        public ServiceClient mockedServiceClient() {
            return mock(ServiceClient.class);
        }
    }

    @Before
    public void setup() {
        reset(mockedServiceClient);
    }

    @Test
    public void shouldBehaveACertainWay() {
        // customize mock, call component methods, assert results...
    }
}

package com.example.myapp;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = MyApplication.class)
@WebAppConfiguration
@ActiveProfiles("test")
public class Component1TestWithRealCommunication {

    @Autowired
    Component1 component1; // <-- the thing we're testing. wants the real implementations in this test.

    @Autowired
    ServiceClient mockedServiceClient;

    @Before
    public void setup() {
        reset(mockedServiceClient);
    }

    @Test
    public void shouldBehaveACertainWay() {
        // call component methods, assert results...
    }
}

위의 설정 문제는 MyApplication에서 구성한 구성 요소 검사가 Component1TestWithFakeCommunication.ContextConfiguration을 선택하기 때문에 실제 ServiceClient 구현이 필요한 Component1TestWithRealCommunication에서도 모의 ServiceClient가 발생합니다.

@Autowired 생성자를 사용할 수는 있지만 두 테스트 모두에서 구성 요소를 직접 빌드 할 수는 있지만 복잡한 설정이 필요한 충분한 양의 Spring TestContext를 설정해야합니다 (예 : Spring Data JPA 리포지토리, 라이브러리의 구성 요소 스프링 컨텍스트에서 콩을 가져 오는 응용 프로그램 외부). Spring 컨텍스트 내에서 특정 bean 정의를 로컬 적으로 오버라이드 할 수있는 테스트 내에서 Spring 컨피규레이션을 중첩하는 것은 이것을 수행하는 깔끔한 방법처럼 느껴진다. 유일한 단점은 이러한 중첩 된 구성이 결국 MyApplication (구성 요소가 앱 패키지를 검색)에서 구성을 기반으로하는 모든 Spring TestContext 테스트에 영향을 미친다는 것입니다.

각 테스트 클래스에서 로컬로 오버라이드 된 빈을 몇 개만 가지고 테스트를위한 "대부분의 실제"스프링 컨텍스트를 얻도록 설정을 수정하려면 어떻게해야합니까?

해결법

  1. ==============================

    1.다음은 현재 테스트 클래스에만 적용 할 수있는 새로운 위조 통신 프로파일을 도입하여 목표를 달성하는 데 도움이됩니다.

    다음은 현재 테스트 클래스에만 적용 할 수있는 새로운 위조 통신 프로파일을 도입하여 목표를 달성하는 데 도움이됩니다.

    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringApplicationConfiguration(classes = MyApplication.class)
    @WebAppConfiguration
    @ActiveProfiles({"test", "fake-communication"})
    public class Component1TestWithFakeCommunication {
    
        // @Autowired ...
    
        @Profile("fake-communication")
        @Configuration
        static class ContextConfiguration {
            @Bean
            @Primary
            public ServiceClient mockedServiceClient() {
                return mock(ServiceClient.class);
            }
        }
    }
    
  2. ==============================

    2.@SpringBootTest가있는 경우 @MockBean으로 모의하려는 서비스에만 주석을 달 수 있습니다. 저것과 같이 쉬운.

    @SpringBootTest가있는 경우 @MockBean으로 모의하려는 서비스에만 주석을 달 수 있습니다. 저것과 같이 쉬운.

  3. ==============================

    3.나는 두 가지 일을 할 것이다.

    나는 두 가지 일을 할 것이다.

    Spring은 테스트 빈을 조롱하기에 충분한 정보를 제공해야하지만 런타임시 ApplicationContext가 테스트 빈을 알아 채지 못하게해야한다.

  4. ==============================

    4.다른 명시 적 프로파일을 사용하여 테스트 구성을 선택하지 않도록 할 수 있습니다 (다른 대답에서 제안 된 것처럼). 나는 또한 그것을했고 심지어 도서관 지원을 만들었다.

    다른 명시 적 프로파일을 사용하여 테스트 구성을 선택하지 않도록 할 수 있습니다 (다른 대답에서 제안 된 것처럼). 나는 또한 그것을했고 심지어 도서관 지원을 만들었다.

    그러나 Spring-Boot는 영리하며이 문제를 자동으로 해결하는 "유형 필터"가 내장되어 있습니다. 이 작업을 수행하려면 @ComponentScan 주석을 제거해야합니다. @ComponentScan 주석은 테스트 구성을 찾아서 @SpringBootApplication이 작업을 수행하게합니다. 귀하의 예에서는 다음을 제거하십시오.

    @SpringBootApplication
    @ComponentScan(
        basePackageClasses = {
                MyApplication.class,
                ImportantConfigurationFromSomeLibrary.class,
                ImportantConfigurationFromAnotherLibrary.class})
    

    다음과 같이 바꿉니다.

    @SpringBootApplication(scanBasePackageClasses= {
                MyApplication.class,
                ImportantConfigurationFromSomeLibrary.class,
                ImportantConfigurationFromAnotherLibrary.class})
    

    또한 테스트를 @SpringBootTest로 주석 처리해야 할 수도 있습니다. 이것은 현재 테스트에있는 것을 제외하고 내부 클래스 구성 (및 구성 요소)을 자동 스캔하지 않아야합니다.

  5. from https://stackoverflow.com/questions/39300167/how-to-use-componentscan-together-with-test-specific-contextconfigurations-in-s by cc-by-sa and MIT license