source

통합 테스트에서 콩 덮어쓰기

factcode 2022. 9. 11. 17:10
반응형

통합 테스트에서 콩 덮어쓰기

Spring-Boot "RestTemplate" @Configuration " @Configuration " ( " RestTemplate " ) 。통합 테스트에서는 외부 서비스에 접속하고 싶지 않기 때문에 RestTemplate를 조롱하고 싶습니다.어떤 응답을 기대하는지 알고 있습니다.저는 통합 테스트 패키지가 실제 구현보다 우선되기를 바라며 통합 테스트 패키지에 다른 구현을 제공하려고 했지만 로그를 확인하는 것은 반대입니다: 실제 구현이 테스트 패키지보다 우선합니다.

Test Config test test 、 test test test test test test test test test test test test test test test test test test test test test?

이것은 설정 파일입니다.

@Configuration
public class RestTemplateProvider {

    private static final int DEFAULT_SERVICE_TIMEOUT = 5_000;

    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate(buildClientConfigurationFactory());
    }

    private ClientHttpRequestFactory buildClientConfigurationFactory() {
        HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
        factory.setReadTimeout(DEFAULT_SERVICE_TIMEOUT);
        factory.setConnectTimeout(DEFAULT_SERVICE_TIMEOUT);
        return factory;
    }
}

통합 테스트:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = TestConfiguration.class)
@WebAppConfiguration
@ActiveProfiles("it")
public abstract class IntegrationTest {}

Test Configuration 클래스:

@Configuration
@Import({Application.class, MockRestTemplateConfiguration.class})
public class TestConfiguration {}

마지막으로 MockRestTemplate 구성

@Configuration
public class MockRestTemplateConfiguration {

    @Bean
    public RestTemplate restTemplate() {
        return Mockito.mock(RestTemplate.class)
    }
}

.4 Spring Boot 1.4.x 를 사용하는 .@MockBean★★★★★★★★★★★★★★★★★★★★★★★★★★★

코멘트에 대한 반응:

하려면 , 「」를 사용하지 .@DirtiesContext단, , 「」를 사용합니다.@ContextConfiguration(name = "contextWithFakeBean")디폴트 콘텍스트는 캐시에 보관 유지하면서 별도의 콘텍스트가 생성됩니다.스프링은 두 가지(또는 컨텍스트 수)를 모두 캐시에 저장합니다.

대부분의 테스트에서는 디폴트의 폴리싱되지 않은 구성을 사용하고 있습니다만, 4~5개의 테스트에서는 가짜 콩을 사용하고 있습니다.기본 컨텍스트를 적절하게 재사용할 수 있습니다.

. 1.합니다.@Primary★★★★

@Configuration
public class MockRestTemplateConfiguration {

    @Bean
    @Primary
    public RestTemplate restTemplate() {
        return Mockito.mock(RestTemplate.class)
    }
}

그나저나 나는 가짜 봄콩에 대한 블로그 글을 썼다.

2. 단, Spring Rest Template 테스트 지원에 대해 살펴보는 것이 좋습니다.다음은 간단한 예입니다.

  private MockRestServiceServer mockServer;

  @Autowired
  private RestTemplate restTemplate;

  @Autowired
  private UsersClient usersClient;

  @BeforeMethod
  public void init() {
    mockServer = MockRestServiceServer.createServer(restTemplate);
  }

  @Test
  public void testSingleGet() throws Exception {
    // GIVEN
    int testingIdentifier = 0;
    mockServer.expect(requestTo(USERS_URL + "/" + testingIdentifier))
      .andExpect(method(HttpMethod.GET))
      .andRespond(withSuccess(TEST_RECORD0, MediaType.APPLICATION_JSON));


    // WHEN
    User user = usersClient.getUser(testingIdentifier);

    // THEN
    mockServer.verify();
    assertEquals(user.getName(), USER0_NAME);
    assertEquals(user.getEmail(), USER0_EMAIL);
  }

자세한 예는 이쪽의 Github repo에서 확인할 수 있습니다.

에 문제가 은, 「」, 「이러다」를 사용하고 있는 입니다.@Configuration를 참조하십시오.이것으로 메인 설정이 바뀝니다.대신 를 사용하여 기본 구성을 추가(덮어쓰기)합니다.

46.3.2 테스트 구성 검출

프라이머리 설정을 커스터마이즈 하는 경우는, 네스트된 @TestConfiguration 클래스를 사용할 수 있습니다.응용 프로그램의 프라이머리 구성 대신 사용되는 네스트된 @Configuration 클래스와 달리 네스트된 @TestConfiguration 클래스는 응용 프로그램의 프라이머리 구성과 함께 사용됩니다.

Spring Boot 사용 예:

메인 클래스

@SpringBootApplication() // Will scan for @Components and @Configs in package tree
public class Main{
}

메인 구성

@Configuration
public void AppConfig() { 
    // Define any beans
}

테스트 설정

@TestConfiguration
public void AppTestConfig(){
    // override beans for testing
} 

테스트 클래스

@RunWith(SpringRunner.class)
@Import(AppTestConfig.class)
@SpringBootTest
public void AppTest() {
    // use @MockBean if you like
}

주의: 덮어쓰는 콩도 모두 작성됩니다.@Profile에 나타내지 @Configuration.

@MockBean콩 오버라이딩

하려고 합니다.@MockBean실제 실장을 잊기 위해서: 일반적으로 슬라이스 테스트나 인테그레이션 테스트에서는 테스트하고 있는 클래스가 있는 콩을 로드하지 않고 이들 콩을 통합 테스트하고 싶지 않은 경우에 사용합니다.
으로 그들을 .null테스트를 완료하기 위한 최소한의 행동을 조롱할 것입니다.

@WebMvcTest 레이어를 않기 에 그 한 경우가 .@SpringBootTest또, 테스트 설정으로 bean 설정의 서브셋만을 지정하는 경우에도, 다음과 같이 요구될 수 있습니다.

가능한 한 에, 「실제 컴포넌트」는 않는 것이 .@MockBean덮어쓰는 이 콩을 덮어쓰게 됩니다. 콩을 덮어쓰게 됩니다.

@SpringBootTest({"spring.main.allow-bean-definition-overriding=true"})
@Import(FooTest.OverrideBean.class)
public class FooTest{    

    @Test
    public void getFoo() throws Exception {
        // ...     
    }

    @TestConfiguration
    public static class OverrideBean {    

        // change the bean scope to SINGLETON
        @Bean
        @Scope(ConfigurableBeanFactory.SINGLETON)
        public Bar bar() {
             return new Bar();
        }

        // use a stub for a bean 
        @Bean
        public FooBar BarFoo() {
             return new BarFooStub();
        }

        // use a stub for the dependency of a bean 
        @Bean
        public FooBar fooBar() {
             return new FooBar(new StubDependency());
        }

    }
}

좀 더 깊이 파고들면, 제 두 번째 답을 보세요.

다음 방법으로 문제를 해결했습니다.

@SpringBootTest(classes = {AppConfiguration.class, AppTestConfiguration.class})

대신

@Import({ AppConfiguration.class, AppTestConfiguration.class });

내 경우 테스트는 앱과 동일한 패키지에 포함되어 있지 않습니다.따라서 AppConfiguration.class(또는 App.class)를 명시적으로 지정해야 합니다.만약 당신이 테스트에서 같은 패키지를 사용한다면, 당신은 그냥 쓸 수 있을 것이다.

@SpringBootTest(classes = AppTestConfiguration.class)

(동작하지 않는) 대신

@Import(AppTestConfiguration.class );

이것이 매우 다른 것을 보는 것은 꽤 잘 알려져 있다.마마 、 누걸걸걸걸걸 거을을 。을 사용하다하실 수도 있어요.@Import(...)는 선택되지 않습니다.@SpringBootTests는 존재하지만 로그에는 우선되는 빈이 표시됩니다.하지만 그 반대야.

런데, using using using를 @TestConfiguration, ★★★★★★★★★★★★★★★★」@Configuration역시 차이가 없습니다.

@Primary 주석에서는 Bean override는 Spring Boot 1.5.X에서는 동작하지만 Spring Boot 2.1.X에서는 실패합니다.throw 오류:

Invalid bean definition with name 'testBean' defined in sample..ConfigTest$SpringConfig:.. 
There is already .. defined in class path resource [TestConfig.class]] bound

.properties=스프링에게 덮어쓰기를 허용하도록 명시적으로 지시할 것입니다. 을 사용하다

@SpringBootTest(properties = ["spring.main.allow-bean-definition-overriding=true"])

업데이트: application-test.yml에서도 동일한 속성을 추가할 수 있습니다(파일명은 테스트에 사용하는 테스트 프로파일명에 따라 다릅니다).

하나의 메서드만 덮어쓰고 싶었기 때문에 테스트에서 내부 구성 클래스를 선언했습니다.

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class FileNotificationWebhookTest{

    public static class FileNotificationWebhookTestConfiguration {
        @Bean
        @Primary
        public FileJobRequestConverter fileJobRequestConverter() {
            return new FileJobRequestConverter() {
                @Override
                protected File resolveWindowsPath(String path) {
                    return new File(path);
                }
            };
        }
    }
}

하지만,

@SpringBoot에서의 설정 선언테스트가 작동하지 않았습니다.

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,classes = {FileNotificationWebhookTest.FileNotificationWebhookTestConfiguration.class})

또는 @Configuration을 사용하여 테스트 설정에 주석을 달지 않았습니다.

@Configuration
public static class FileNotificationWebhookTestConfiguration {

}

그 결과,

원인: org.springframework.context.Application Context Exception:웹 서버를 시작할 수 없습니다. 중첩된 예외는 org.springframework.context입니다.Application Context Exception:ServletWebServerFactory 빈이 없으므로 ServletWebServerApplicationContext를 시작할 수 없습니다.

(여기에 게재된 다른 투고와는 달리) @Import를 사용하는 것이 효과적이었다.

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@Import(FileNotificationWebhookTest.FileNotificationWebhookTestConfiguration.class)
class FileNotificationWebhookTest {

}

스프링 사용: 5.3.3 (스프링 부트 스타터 포함): 2.4.2

@MockBean는 프로덕션 빌드 대신 모키토 모크를 생성합니다.

Mockito를대체 있는 에는 Mockito를 하여 사용할 것을 합니다.@TestConfiguration1.4및 ('1.4.0')@Primary석입니니다다

@TestConfiguration하고 "사용할 수 있는 컨텍스트"를 합니다.@TestConfiguration조각이 더해져요." " " @PrimaryRestTemplate 를를를를 。

다음의 간단한 예를 참조해 주세요.

@SpringBootTest
public class ServiceTest {

    @TestConfiguration
    static class AdditionalCfg {
        @Primary
        @Bean
        RestTemplate rt() {
            return new RestTemplate() {
                @Override
                public String exec() {
                    return "Test rest template";
                }
            };
        }
    }

    @Autowired
    MyService myService;

    @Test
    void contextLoads() {
       assertThat(myService.invoke()).isEqualTo("Test rest template");
    }
}

이거 진짜 이상하다.

내 경우(Spring Boot 2.6.7), 커스텀 @Primary @Bean을 포함한 @MyTestConfiguration을 @SpringBoot에 Import하기만 하면 됩니다.테스트, 그리고 모든 게 성공했어

내 콩의 이름을 분명히 지어야 할 때 까지 말이야그러다가 갑자기...

@SpringBootTest(
    properties = ["spring.main.allow-bean-definition-overriding=true"],
    classes = [MyTestConfig::class],
)

이 답변과 해당 스레드에 제공된 다른 답변을 함께 확인하십시오.Spring Boot 2.X에서 bean을 덮어쓰는 것입니다.이 경우 이 옵션은 기본적으로 비활성화되어 있습니다.또한 만약 당신이 그 방법을 선택하기로 결정했다면, 그것은 어떻게 Bean Definition DSL을 사용하는지에 대한 몇 가지 아이디어도 가지고 있다.

가장 간단한 해결책은 application.properties에서 이 속성을 설정하는 것입니다.

spring.main.allow-bean-definition-overriding=true

이렇게 하면 콩을 덮어쓸 수 있습니다.

다음으로 테스트에서 컨피규레이션클래스를 만들고 콩에 주석을 붙입니다.

@Bean
@Primary

이렇게 하면 이 콩이 테스트 시 일반적인 콩보다 우선됩니다.

언급URL : https://stackoverflow.com/questions/35742920/overriding-beans-in-integration-tests

반응형