无法找到@SpringBootConfiguration,您需要在测试中使用@ContextConfiguration或@SpringBootTest(classes=...)。

118

我正在使用 Spring Data JPASpring Boot。 应用程序的布局如下:

main
    +-- java
        +-- com/lapots/game/monolith
            +-- repository/relational
                +--RelationalPlayerRepository.java
            +-- web
                +--GrandJourneyMonolithApplication.java
                +-- config
                    +-- RelationalDBConfiguration.java
test
    +-- java
        +-- com/lapots/game/monolith
            +-- repository/relational
                +-- RelationalPlayerRepositoryTests.java
            +-- web
                +-- GrandJourneyMonolithApplicationTests.java

我的对象存储库长这样

public interface RelationalPlayerRepository extends JpaRepository<Player, Long> {
}

此外,为了这些代码库,我提供了一个配置

@Configuration
@EnableJpaRepositories(basePackages = "com.lapots.game.monolith.repository.relational")
@EntityScan("com.lapots.game.monolith.domain")
public class RelationalDBConfiguration {
}

我的主要应用程序长这样

@SpringBootApplication
@ComponentScan("com.lapots.game.monolith")
public class GrandJourneyMonolithApplication {

    @Autowired
    private RelationalPlayerRepository relationalPlayerRepository;

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

    @Bean
    public CommandLineRunner initPlayers() {
        return (args) -> {
            Player p = new Player();
            p.setLevel(10);
            p.setName("Master1909");
            p.setClazz("warrior");

            relationalPlayerRepository.save(p);
        };
    }
}

这个应用程序的测试看起来像这样

@RunWith(SpringRunner.class)
@SpringBootTest
public class GrandJourneyMonolithApplicationTests {

    @Test
    public void contextLoads() {
    }

}

关于代码库的测试看起来像这样

@RunWith(SpringRunner.class)
@DataJpaTest
public class RelationalPlayerRepositoryTests {

    @Autowired
    private TestEntityManager entityManager;

    @Autowired
    private RelationalPlayerRepository repository;

    @Test
    public void testBasic() {
        Player expected = createPlayer("Master12", "warrior", 10);
        this.entityManager.persist(expected);
        List<Player> players = repository.findAll();
        assertThat(repository.findAll()).isNotEmpty();
        assertEquals(expected, players.get(0));
    }

    private Player createPlayer(String name, String clazz, int level) {
        Player p = new Player();
        p.setId(1L);
        p.setName(name);
        p.setClazz(clazz);
        p.setLevel(level);
        return p;
    }
}

但是当我尝试运行测试时,出现了错误。

Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.041 sec <<< FAILURE! - in com.lapots.game.monolith.repository.relational.RelationalPlayerRepositoryTests
initializationError(com.lapots.game.monolith.repository.relational.RelationalPlayerRepositoryTests)  Time elapsed: 0.006 sec  <<< ERROR!
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:70)
at org.springframework.boot.test.context.SpringBootTestContextBootstrapper.getOrFindConfigurationClasses(SpringBootTestContextBootstrapper.java:202)
at org.springframework.boot.test.context.SpringBootTestContextBootstrapper.processMergedContextConfiguration(SpringBootTestContextBootstrapper.java:137)
at org.springframework.test.context.support.AbstractTestContextBootstrapper.buildMergedContextConfiguration(AbstractTestContextBootstrapper.java:409)
at org.springframework.test.context.support.AbstractTestContextBootstrapper.buildDefaultMergedContextConfiguration(AbstractTestContextBootstrapper.java:323)
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:82)
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.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128)
at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103)

问题是什么? 领域 Player 看起来是这样的

@Data
@Entity
@Table(schema = "app", name = "players")
public class Player {
    @Id
    @GeneratedValue
    private Long id;

    @Transient
    Set<Player> comrades;

    @Column(unique = true)
    private String name;

    private int level;

    @Column(name = "class")
    private String clazz;
}

2
如果您使用@ContextConfiguration(classes = GrandJourneyMonolithApplication.class)注释RelationalPlayerRepositoryTests,会发生什么? - Sam Brannen
@SamBrannen 出现了错误,显示“无法使用嵌入式数据源替换 DataSource”。 - lapots
在添加空的 @SpringBootApplication 后,这对我起作用了。 - Gaurav
10个回答

262

src/test/java 的包和 src/main/java 的包应该匹配。

我曾经遇到过相同的问题,其中:

  • 我的 src/main/java 包以com.comp.example 开头,但是
  • src/test/java 包以com.sample.example 开头。

因此,Spring Boot 应用程序无法获取应用程序的配置,它从 @SpringBootApplication 类中获取。

因此,测试用例应该与在 src/main/java 中编写 @SpringBootApplication 的类相同。


2
我正在使用Spring Boot和一个简单的REST控制器。没有使用任何JPA,但在我的控制器测试中遇到了与标题中指定的相同的错误。此外,我正在为我的Spring Boot应用程序使用自定义配置。这个答案(2018年10月19日7:20 Saurabh Parmar)有所帮助。对我来说,根本原因也是包名。我的测试包在src/test/java下与src/main/java下的包不匹配。一旦我解决了这个问题,它就可以工作了。 - VC2019
我在测试包名称中打错了一个字母。 - Heiner
3
我完全忘记添加包名了。这就解决了问题。 - Renato Gama
为了避免需要将测试类的包与生产代码的包进行匹配,只需在SpringBootTest注释中指定要用于加载应用程序上下文的类,如此 @SpringBootTest(classes = Application.class)。 - Emiliano Schiano
1
是的,那正是我的问题。然而,你可以通过以下方式解决这个问题:@SpringBootTest( classes = MyTest.MyTestConfiguration.class ) public class MyTest {// 在此编写你的测试@Configuration @ComponentScan( basePackages = { "com.comp.example", "com.sample.example" } ) static class MyTestConfiguration {}} - antonrud
显示剩余2条评论

38
当Spring Boot启动时,它会从项目的顶部到底部扫描类路径以查找配置文件。您的配置文件位于其他文件下,这就是问题的原因。将您的配置文件移到更高的位置,即monolith包中,一切都会正常。

1
但是在测试中指定配置类不是可能的吗? - lapots
我也移动了"配置(configuration)"类,但没有帮助。 - lapots
2
上面的答案应该是正确的。按照文档中建议的方式构建您的应用程序,测试应该能够查找到配置。您可能由于禁用自动配置的注释而遇到其他问题。也尝试删除@EnableJpaRepositories@EntityScan@ComponentScan - Phil Webb

28

@SpringBootTest有一个名为classes的参数,它接受一个类数组作为配置。将配置文件的类添加到其中,例如:

@SpringBootTest(classes = ConfigFile.class)
@SpringBootTest(classes={com.lapots.game.monolith.web.GrandJourneyMonolithApplication.class})

1
这对我有用:@SpringBootTest(classes = App.class, webEnvironment = WebEnvironment.DEFINED_PORT) - 参见 https://dev59.com/rlcQ5IYBdhLWcg3wA_LH - Sasha Bond

16

测试 src/test/java 文件应该遵循与 src/main/java 相同的目录结构。

输入图像描述


大写的包名不符合Java编码规范。 - Michael

4

如果你的项目中没有可测试的代码,并且你有Spring Boot默认测试类中的默认测试块

@SpringBootTest

class DemoApplicationTests {
    @Test
    void contextLoads() {
    }
}

删除测试注释和contextLoads()方法,修改为:

@SpringBootTest
class DemoApplicationTests {
}

4

在我的情况下,这是由于一些类的[移动|复制/粘贴]导致的。对于某些类,package子句要么被[没有正确更新|不存在],而这些更改并未被IDE捕获。

无论如何,请检查您的项目打包方式。


2

对我来说,通过将主类的路径添加如下,它可以正常工作

@SpringBootTest(classes = {com.ghimire.bookApi.SpringBookApiPracticeApplication.class})

0

只有在@SpringBootTest类中同时包含上下文配置类和应用程序类,我才能解决这个问题。


0

删除文件module-info.java。这对我有用。


0

尽管不是对OP问题的直接回答,但我成功解决了自己在IntelliJ IDEA中遇到的相同错误信息(作为这个问题的标题):

"Maven Dance"™️ 的某些部分 {mvn clean compile,[IntelliJ]Reload All Maven Projects} 对我解决了这个问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接