Spring-boot: Simple WebMvcTest fails with Spring Boot 1.4M3 due to missing SpringBootConfiguration

Created on 18 May 2016  路  15Comments  路  Source: spring-projects/spring-boot

Assuming following test case

package org.sample;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@WebMvcTest
public class SimpleBootTest {

    @Test
    public void nothing(){

    }

}

I got following exception when executing the test in Eclipse:

java.lang.IllegalStateException: Unable to find a @SpringBootConfiguration, you need to use @ContextConfiguration or @SpringBootTest(classes=...) with your test
    at org.springframework.util.Assert.state(Assert.java:392)
    at org.springframework.boot.test.context.SpringBootTestContextBootstrapper.getOrFindConfigurationClasses(SpringBootTestContextBootstrapper.java:149)
    at org.springframework.boot.test.context.SpringBootTestContextBootstrapper.processMergedContextConfiguration(SpringBootTestContextBootstrapper.java:115)
    at org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTestContextBootstrapper.processMergedContextConfiguration(WebMvcTestContextBootstrapper.java:35)
    at org.springframework.test.context.support.AbstractTestContextBootstrapper.buildMergedContextConfiguration(AbstractTestContextBootstrapper.java:412)
    at org.springframework.test.context.support.AbstractTestContextBootstrapper.buildDefaultMergedContextConfiguration(AbstractTestContextBootstrapper.java:326)
    at org.springframework.test.context.support.AbstractTestContextBootstrapper.buildMergedContextConfiguration(AbstractTestContextBootstrapper.java:277)
    at org.springframework.test.context.support.AbstractTestContextBootstrapper.buildTestContext(AbstractTestContextBootstrapper.java:112)
    at org.springframework.boot.test.context.SpringBootTestContextBootstrapper.buildTestContext(SpringBootTestContextBootstrapper.java:73)
    at org.springframework.test.context.TestContextManager.<init>(TestContextManager.java:120)
    at org.springframework.test.context.TestContextManager.<init>(TestContextManager.java:105)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTestContextManager(SpringJUnit4ClassRunner.java:152)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.<init>(SpringJUnit4ClassRunner.java:143)
    at org.springframework.test.context.junit4.SpringRunner.<init>(SpringRunner.java:49)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:104)
    at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:86)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
    at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
    at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:33)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createUnfilteredTest(JUnit4TestLoader.java:84)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createTest(JUnit4TestLoader.java:70)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.loadTests(JUnit4TestLoader.java:43)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:444)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:670)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)


After adding SpringBootTest annotation

package org.sample;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.boot.test.context.SpringBootTest;

@RunWith(SpringRunner.class)
@WebMvcTest
@SpringBootTest
public class SimpleBootTest {

    @Test
    public void nothing(){

    }

}

I get following exception:

java.lang.IllegalStateException: Configuration error: found multiple declarations of @BootstrapWith for test class [org.sample.SimpleBootTest]: [@org.springframework.test.context.BootstrapWith(value=class org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTestContextBootstrapper), @org.springframework.test.context.BootstrapWith(value=class org.springframework.boot.test.context.SpringBootTestContextBootstrapper)]
    at org.springframework.test.context.BootstrapUtils.resolveExplicitTestContextBootstrapper(BootstrapUtils.java:158)
    at org.springframework.test.context.BootstrapUtils.resolveTestContextBootstrapper(BootstrapUtils.java:126)
    at org.springframework.test.context.TestContextManager.<init>(TestContextManager.java:105)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTestContextManager(SpringJUnit4ClassRunner.java:152)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.<init>(SpringJUnit4ClassRunner.java:143)
    at org.springframework.test.context.junit4.SpringRunner.<init>(SpringRunner.java:49)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:104)
    at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:86)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
    at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
    at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:33)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createUnfilteredTest(JUnit4TestLoader.java:84)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createTest(JUnit4TestLoader.java:70)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.loadTests(JUnit4TestLoader.java:43)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:444)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:670)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)



What is the correct way of using WebMvcTests?

Thanks,
Jens

invalid

Most helpful comment

Thanks.

As I suspected, this isn't a bug. The documentation on detecting test configuration says:

The search algorithm works up from the package that contains the test until it finds a @SpringBootApplication or @SpringBootConfiguration annotated class. As long as you鈥檝e structure your code in a sensible way your main configuration is usually found.

Your application code is in com.example yet your test is in org.sample so your application configuration isn't found. You need to move your tests into com.example or a sub-package.

All 15 comments

Thanks for getting in touch, but it feels like this is a question that would be better suited to Stack Overflow. As mentioned in the guidelines for contributing, we prefer to use GitHub issues only for bugs and enhancements. Feel free to update this issue with a link to the re-posted question (so that other people can find it) or add some more details if you feel this is a genuine bug.

No, it is a bug report... It is a minimal example which fails in Spring Boot 1.4M3.

Reference:
https://spring.io/blog/2016/04/15/testing-improvements-in-spring-boot-1-4#testing-the-spring-mvc-slice

Perhaps you can provide a sample that reproduces the problem? It's impossible to say why a @SpringBootConfiguration annotated class can't be found without seeing a complete example.

Running
gradle test

for example app https://github.com/jgoldhammer/gh-5987 brings up the error...

Thanks.

As I suspected, this isn't a bug. The documentation on detecting test configuration says:

The search algorithm works up from the package that contains the test until it finds a @SpringBootApplication or @SpringBootConfiguration annotated class. As long as you鈥檝e structure your code in a sensible way your main configuration is usually found.

Your application code is in com.example yet your test is in org.sample so your application configuration isn't found. You need to move your tests into com.example or a sub-package.

I just upgrade to 1.4RC1 and ran into this for the same reason. Spring must be more strict about this than it was previously as the class in question has always been at a higher level in the package hierarchy than the application class.

@robmoore

Spring must be more strict about this than it was previously

@SpringBootTest is new in 1.4, are you seeing a regression in your existing tests? If so, could you please open a new issue and provide a sample that replicates the problem.

@philwebb I don't believe it is a regression given @wilkinsona's comment above. I did swap out @SpringApplicationConfiguration with @SpringBootTest but the test class was in a package above the actual application class. Upon further review, it's seems like the only reason it worked before is that I specified a value for the classes parameter (@SpringApplicationConfiguration(classes = MyApplication.class)). I removed the parameter as I thought it was redundant but I suspect that if I had left it, it would have behaved as before. I'm happy to test out this behavior if you'd like. Sorry to create confusion with my previous comment.

@robmoore That makes sense, thanks! You can use @SpringBootTest(classes=MyApplication.class) if you want to use the new annotation but refer to a specific config.

@philwebb @SpringBootTest wont work with @WebMvcTest because they both have @BootstrapWith annotations

EDIT: sorry replaced with @ContextConfiguration like the error says and it works perfectly

If you, say, base your application on one of the examples from the Spring Boot guides that is _not_ using @SpringBootApplication annotation then you're likely to see this error.

For example, replace:

@Configuration @ComponentScan(basePackages = "com.example.main") @EnableAutoConfiguration

with

@SpringBootApplication(scanBasePackages = "com.example.main")

should get you going.

Thanks @s5b, we plan to refresh the guides at some point since most were written before @SpringBootApplication existed.

I stumbled into the same error using spock framework and spring boot 1.4.0

To fix it I had to put the spec in the same package of the SpringBootApplication.

I had this error in 1.4.2
Fixed it by adding @ContextConfiguration(classes = Application.class)

Thanks for @s5b (when your situation is @SpringBootApplication in Application.class and @WebMvcTest in Test.class ) and @akamuza (when your situation is @Configuration @ComponentScan @EnableAutoConfiguration in Application.class + @WebMvcTest @ContextConfiguration in Test.class).
Both are OK.

Was this page helpful?
0 / 5 - 0 ratings