简体   繁体   中英

How to bootstrap a test in Spring Boot manually (without @SpringBootTest-Annotation)

I'm migrating a project from Play Framework to Spring Boot with Web Flux and got it basically running when I start it manually. However, most of my tests are not working yet. (My play.Application obviously can't inject a org.springframework.beans.factory.BeanFactory as no implementation was bound.) With Play Framework I used to create an application in my tests with:

play.Application app = new play.inject.guice.GuiceApplicationBuilder()
    .bindings(
        // here I added a few manual bindings (e.g. mocks)
    ).build();
// Then I could get "beans" out of it:
MyFancyService fancyService = app.injector().instanceOf(MyFancyService.class);
// Or send Http-Requests to it:
Result response = route(app, request);

How to do that with Spring Boot?

I've tried/considered:

  • Annotating all my tests with @SpringBootTest(SpringBootTest.WebEnvironment.MOCK) or @WebFluxTest , and adding an @Autowired WebTestClient webClient . However especially during the migration I would rather not change all my tests too much (the code above is currently only in one place in a org.junit.Rule ).
  • Creating an ApplicationContext with new SpringBootTestContextBootstrapper().buildTestContext().getApplicationContext() , but could not figure out how to send request to it.

Basically I'm looking for these three key features in Spring Boot (with Web Flux if possible):

  1. Adding/Injecting some mocks as services (manually add bindings to the BeanFactory)
  2. Accessing some automatically set up services (something like app.getInstanceOf(MyFancyService.class) )
  3. Sending Http Requests

Finally I figured it out more or less:

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
public class WithApp extends ExternalResource {

    private final WebTestClient webTestClient;

    public WithApp() {
        SpringBootTestContextBootstrapper springBootTestContextBootstrapper = new SpringBootTestContextBootstrapper();
        springBootTestContextBootstrapper.setBootstrapContext(new DefaultBootstrapContext(WithApp.class, new DefaultCacheAwareContextLoaderDelegate()));
        MergedContextConfiguration config = springBootTestContextBootstrapper.buildMergedContextConfiguration();
        ApplicationContext app = new ApplicationContextLoader().loadContext(config);
        MyBean mockedBean = app.getBean(MyBean.class);
        this.webTestClient = WebTestClient.bindToApplicationContext(app).build();
    }

    public WebTestClient.ResponseSpec call(HttpMethod method, String uri, Object body) {
        return webTestClient.method(method).uri(uri).bodyValue(body).exchange();
    }

    @Component
    public static class Config {
        @Primary
        @Bean
        public MyBean getMyBeanForTest() {
            return mock(MyBean.class);
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM