Forcing Spring Boot to NOT use EmbeddedWebApplicationContext?
Asked Answered
T

2

0

I have a Spock test case where I want to load a Spring application. I have a very rudimentary Groovy class that is my config object:

@Configuration
@EnableAutoConfiguration
class TestConfig {
  @Bean
  Map createSillyMsgMap() {
    ["sillyMsg" : "This is a silly message"]
  }
  public static void main(String[] args) {
    println "TestConfig.main(${args})"
  }
}

Obviously, this is isn't very useful, but it serves as an example. For convenience, I've also added the main method in that class. My test class just tries to instantiate this as a Spring Boot Application. Something like this:

class AppContextSpec extends Specification {
  def "testSpringApplication"() {
    given: "a Spring Configuration"
    SpringApplication app = new SpringApplication(TestConfig)
    app.headless = true 
    app.webEnvironment = false
    app.applicationContextClass = AnnotationConfigApplicationContext

    expect: "the Spring Application to be able to start"
    ConfigurableApplicationContext ctxt = app.run((String[]) ["blah"])
  }
}

I'm trying to force Spring Boot to NOT use the EmbeddedWebApplicationContext by explicitly setting the webEnvironment property to false. But no matter what I do, Spring Boot insists on starting a Tomcat server, and it does seem to pull in other resources in the source tree that are marked with @Component and/or @Configuration. There are several other application contexts on the classpath, and certainly jar files that imply web service kind of stuff, but I'm very surprised that what's on the classpath should take precedence over explicit configuration through the webEnvironment property. I'm using Gradle 1.12 as the build system, and the Spring Boot version is 1.1.4, and I'm using Groovy 2.3.6 with Spock 0.7-groovy-2.0. Any help with this is appreciated.

Am I doing something completely out of the norm here? Thanks.

Tsunami answered 11/8, 2014 at 23:18 Comment(0)
P
0

You probably shouldn't be trying to bootstrap the Spring Boot application context on your own like you are doing.

The following code creates an integration testing environment without starting the embedded servlet container (although if you want to start the embedded servlet container it would be very easy to do with a couple more annotations):

@ContextConfiguration(loader = SpringApplicationContextLoader.class, classes = TestConfig.class)
class ExampleSpec extends Specification {

    // ...

}

You'll also have to have the 'org.spockframework:spock-spring:0.7-groovy-2.0' dependency present on your test classpath

Check out this part of the Spring Boot official documentation and this SO question

Peasecod answered 12/8, 2014 at 15:18 Comment(4)
Thanks! That worked. I used @Autowired ApplicationContext appContext inside the test, and that seemed to work. Is there a more "spocky" or "Spring Bootable" way to get the app context out? Seems logical that it would be available through a property on the Specification itself after it has been loaded.Tsunami
Glad that it worked! I am not aware of a more Spock idiomatic way of doing the wiring I'm afraid.Peasecod
I'm still curious as to why my original test didn't work. Loading a SpringApplication like that is documented in the Spring Boot docs. Just wondering if it's specifically incompatible with Spock.Tsunami
I haven't tried to bootstrap the application context like you tried, so I don't have any pointers on thatPeasecod
S
1

In case where you are not writing test and therefore you can't use @ContextConfiguration

Instead of simple SpringApplication.run(MyDomainSpringConfig.class, args);

Construct and run your SpringApplication like this...

SpringApplication application = new SpringApplication(MyDomainSpringConfig.class);
application.setApplicationContextClass(AnnotationConfigApplicationContext.class);
application.run(args);

Verified in Spring Boot 1.2.1

Smollett answered 15/1, 2015 at 20:50 Comment(1)
Anthavio, that's exactly what I was doing in the test shown in my original question, although the test was written in Groovy, not Java :-)Tsunami
P
0

You probably shouldn't be trying to bootstrap the Spring Boot application context on your own like you are doing.

The following code creates an integration testing environment without starting the embedded servlet container (although if you want to start the embedded servlet container it would be very easy to do with a couple more annotations):

@ContextConfiguration(loader = SpringApplicationContextLoader.class, classes = TestConfig.class)
class ExampleSpec extends Specification {

    // ...

}

You'll also have to have the 'org.spockframework:spock-spring:0.7-groovy-2.0' dependency present on your test classpath

Check out this part of the Spring Boot official documentation and this SO question

Peasecod answered 12/8, 2014 at 15:18 Comment(4)
Thanks! That worked. I used @Autowired ApplicationContext appContext inside the test, and that seemed to work. Is there a more "spocky" or "Spring Bootable" way to get the app context out? Seems logical that it would be available through a property on the Specification itself after it has been loaded.Tsunami
Glad that it worked! I am not aware of a more Spock idiomatic way of doing the wiring I'm afraid.Peasecod
I'm still curious as to why my original test didn't work. Loading a SpringApplication like that is documented in the Spring Boot docs. Just wondering if it's specifically incompatible with Spock.Tsunami
I haven't tried to bootstrap the application context like you tried, so I don't have any pointers on thatPeasecod

© 2022 - 2024 — McMap. All rights reserved.