programing

SpringJunit4에서 테스트 고유의 ContextConfiguration과 함께 @ComponentScan을 사용하는 방법Test Runner?

megabox 2023. 2. 15. 21:49
반응형

SpringJunit4에서 테스트 고유의 ContextConfiguration과 함께 @ComponentScan을 사용하는 방법Test Runner?

Spring Boot 어플리케이션을 테스트하고 있습니다.저는 몇 가지 테스트 클래스가 있는데, 각각의 테스트 클래스에는 다른 종류의 조롱콩이나 맞춤형 콩이 필요합니다.

다음은 설정의 개요입니다.

src/main/main:

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/module:

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...
    }
}

위 설정의 문제는 My Application에서 설정된 컴포넌트 스캔에서 Component1이 선택된다는 것입니다.Test With Fake Communication.Context Configuration을 통해 Component 1에서도 모의 Service Client를 얻을 수 있습니다.Test With Real Communication에서 실제 Service Client를 구현할 수 있습니다.

두 테스트 모두 @Autowired 컨스트럭터를 사용하여 컴포넌트를 직접 빌드할 수 있지만 복잡한 셋업으로 충분한 양이 있습니다(예를 들어 Spring Data JPA 저장소, Spring 컨텍스트에서 콩을 꺼내는 앱 외부의 컴포넌트 등).Spring 컨텍스트 내에서 특정 bean 정의를 로컬로 덮어쓸 수 있는 Spring 구성을 테스트 내에 네스트하는 것은 이를 위한 클린한 방법이라고 생각합니다.단, 이러한 네스트된 구성이 My Application(컴포넌트 스캔)을 기반으로 하는 모든 Spring Test Context 테스트에 영향을 미칩니다.패키지)

각 테스트 클래스에 로컬로 오버라이드된 콩을 몇 개만 사용하여 테스트에 대해 "거의 실제" 스프링 컨텍스트를 얻을 수 있도록 하려면 어떻게 해야 합니까?

다음은 새로운 기술을 도입하여 목표를 달성하는 데 도움이 될 것입니다.fake-communication 현재 테스트 클래스에만 적용할 수 있는 프로파일입니다.

@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);
        }
    }
}

(다른 답변에서 제시된 바와 같이) 이러한 테스트 설정이 선택되는 것을 피하기 위해 추가 명시 프로파일을 사용할 수 있습니다.그리고 그것을 위한 도서관 지원도 만들었습니다.

그러나 Spring-Boot에는 이 문제를 자동으로 해결하기 위한 "유형 필터"가 내장되어 있습니다.이 작업을 수행하려면 다음 명령을 삭제해야 합니다.@ComponentScan주석은 테스트 구성을 찾고, 이 주석은 테스트 구성이@SpringBootApplication일을 하다이 예에서는, 다음의 항목을 삭제합니다.

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

다음으로 대체한다.

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

, 시험 할 .@SpringBootTest이렇게 하면 현재 테스트에 존재하는 구성(및 컴포넌트)을 제외한 모든 내부 클래스 구성(및 컴포넌트)이 자동으로 스캔되지 않습니다.

「 」가 @SpringBootTest 조롱하고 싶은 을 달면 .@MockBean그것처럼 간단해.

저는 몇 가지 일을 하고 싶습니다.

  1. 클래스를 사용하지 않도록 .@ComponentScan먹어버리죠.
  2. »Component1TestWithFakeCommunication, 변경@SpringApplicationConfiguration(classes = MyApplication.class)로로 합니다.@SpringApplicationConfiguration(classes = {MyApplication.class, Component1TestWithFakeCommunication.ContextConfiguration.class})

를 스프링에 할 수 할 수 .ApplicationContext네네테콩도콩콩콩해해해해해해해해해해 。

언급URL : https://stackoverflow.com/questions/39300167/how-to-use-componentscan-together-with-test-specific-contextconfigurations-in-s

반응형