1. The exception

When we test springboot application , sometimes we got IllegalStateException: unable to find @SpringBootConfiguration exception,like this:

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:173)
    at org.springframework.boot.test.context.SpringBootTestContextBootstrapper.processMergedContextConfiguration(SpringBootTestContextBootstrapper.java:133)
    at org.springframework.test.context.support.AbstractTestContextBootstrapper.buildMergedContextConfiguration(
      ....


Process finished with exit code 255

2. The project layout

At first , the project layout is as follows:

my-test-project
  +--pom.xml
  +--src
    +--main
      +--com
        +--example1
          +--Application.java
    +--test
      +--com
        +--example2
          +--TestAsync.java

The Application.java code is:

package com.example1; //notice this package


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

The test code is:

package com.example2; //notice this package name


import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class TestAsync {
...
}

eg.

  • The @SpringBootApplication is Application.java, this class has a package named com.example1
  • The test class’ package is com.example2,which is not the same as the @SpringBootApplication package name nor is the subpackage of it.

This picture shows the package difference.

package_difference

3. The reason of this Unable to find @SpringBootConfiguration exception

The real reason of the Unable to find @SpringBootConfiguration exception is the test class can not find the @SpringBootApplication.

But why is that happened? I do have a @SpringBootApplication class, why the test class can not see it?

Because the @SpringBootTest class has a specific mechanism of finding the @SpringBootApplication , as the following picture shows:

package_find_mechanism

As the picture shows, the @SpringBootTest class would find the @SpringBootApplication from its package com.example2 to com and to /, if still not found, it would throw the Unable to find @SpringBootConfiguration exception.

This is the official description of this mechanism:

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’ve structure your code in a sensible way your main configuration is usually found.

3. How to solve this problem

There are three ways to solve this problem/Exception:

  • Move your test class to com.example1 package, which is the same as the @SpringBootAplication class
  • Move your test class to a subpackage of com.example1, for example, com.example1.test
  • Use @SpringBootTest(classes = Application.class),where the Application.class is the @SpringBootApplication class

3.1 Way 1 demo

solve_way_1

3.2 way2 demo

solve_way_2

3.3 The 3rd way

Change the @SpringBootTest class as follows:

package com.example2; 

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.example1.Application;//notice this line


@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class) //notice this line

public class TestAsync {
...
}

As the comment says, you should notice that there are two difference with the original version:

  • We import the com.example1.Application
  • We add params to @SpringBootTest annotation to specify the @SpringBootApplication class

This means you need not to find it, just use it.

Now run test again, the exception disappeared.

You can find detail documents about the springboot here: