ChatGPT解决这个技术问题 Extra ChatGPT

执行 JpaTest 时找不到 @SpringBootConfiguration

我是框架新手(刚刚通过了课程),这是我第一次使用 Spring Boot。

我正在尝试运行一个简单的 Junit 测试,以查看我的 CrudRepositories 是否确实有效。

我不断收到的错误是:

无法找到 @SpringBootConfiguration,您需要使用 @ContextConfiguration 或 @SpringBootTest(classes=...) 与您的测试 java.lang.IllegalStateException

Spring Boot 不会自行配置吗?

我的测试班:

@RunWith(SpringRunner.class)
@DataJpaTest
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class JpaTest {

@Autowired
private AccountRepository repository;

@After
public void clearDb(){
    repository.deleteAll();
}

 @Test
 public void createAccount(){
     long id = 12;
     Account u = new Account(id,"Tim Viz");
     repository.save(u);

     assertEquals(repository.findOne(id),u);

 }


 @Test
 public void findAccountByUsername(){
     long id = 12;
     String username = "Tim Viz";
     Account u = new Account(id,username);
     repository.save(u);

     assertEquals(repository.findByUsername(username),u);

 }

我的 Spring Boot 应用程序启动器:

@SpringBootApplication
@EnableJpaRepositories(basePackages = {"domain.repositories"})
@ComponentScan(basePackages = {"controllers","domain"})
@EnableWebMvc
@PropertySources(value    {@PropertySource("classpath:application.properties")})
    @EntityScan(basePackages={"domain"})
    public class Application extends SpringBootServletInitializer {
        public static void main(String[] args) {
            ApplicationContext ctx = SpringApplication.run(Application.class, args);         

        }
    }

我的仓库:

public interface AccountRepository extends CrudRepository<Account,Long> {

    public Account findByUsername(String username);

    }
}

T
Thomas Kåsene

事实上,Spring Boot 确实在很大程度上设置了自己。您可能已经删除了很多您发布的代码,尤其是在 Application 中。

我希望您已包含所有类的包名称,或者至少包含 ApplicationJpaTest 的包名称。关于 @DataJpaTest 和其他一些注解的事情是,它们会在当前包中查找 @SpringBootConfiguration 注解,如果在其中找不到它,则会遍历包层次结构直到找到它。

例如,如果您的测试类的完全限定名称是 com.example.test.JpaTest,而您的应用程序的名称是 com.example.Application,那么您的测试类将能够找到 @SpringBootApplication(其中是 @SpringBootConfiguration)。

但是,如果应用程序位于包层次结构的不同分支中,例如 com.example.application.Application,它将找到它。

例子

考虑以下 Maven 项目:

my-test-project
  +--pom.xml
  +--src
    +--main
      +--com
        +--example
          +--Application.java
    +--test
      +--com
        +--example
          +--test
            +--JpaTest.java

然后是 Application.java 中的以下内容:

package com.example;

@SpringBootApplication
public class Application {

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

接下来是JpaTest.java的内容:

package com.example.test;

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

    @Test
    public void testDummy() {
    }
}

一切都应该正常工作。如果您在 src/main/com/example 中创建一个名为 app 的新文件夹,然后将 Application.java 放入其中(并更新文件中的 package 声明),则运行测试会出现以下错误:

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


问候,感谢您提供解决方案,我使用 Maven 数据包设置,使用不同的测试包和应用程序代码。如果我解释正确你所说的是,我必须将我的测试包指向应用程序类?然后它会找到SpringConfiguration?
如果“maven 数据包”是指“模块”,那么是的,您的测试类所在的模块必须依赖于 Application 所在的模块。但是,如果您的意思是 src/mainsrc/test,那么这些文件夹不是包层次结构的一部分。也许你最好用截图或项目结构的解释来更新你的问题。
+--test +--com +--example +--JpaTest.java 也可以
@ThomasBillet 您最终使用了什么项目结构?我发现默认结构是 src/main/javasrc/test/java
@ThomasKåsene 在我的情况下,当我尝试为服务层编写测试时,会出现与此问题相同的错误,并且我的结构类似于 softwareengineering.stackexchange.com/a/323746/214216 您能否建议为此结构编写单元测试的方法?非常感谢。
m
mrts

配置附加到应用程序类,因此以下将正确设置所有内容:

@SpringBootTest(classes = Application.class)

JHipster 项目 here 中的示例。


这似乎是完美的解决方案。我不需要移动任何类或文件夹。
即使 Application 类确实存在,我仍然会收到 ClassNotFound 异常。您的链接也不再有效。
@Praytic,感谢您对无效链接的提醒!我刚刚更新了它。至于 ClassNotFound 异常,请查看链接中的示例。
这简直太完美了!更准确地说,这解决了 Thomas 在他的帖子中提出的问题 如果应用程序驻留在包层次结构的不同分支中,但是,如 com.example.application.Application,它不会找到它。
n
naXa stands with Ukraine

值得检查您是否重构了带有 @SpringBootApplication 注释的主类的包名称。在这种情况下,测试用例应该在适当的包中,否则它将在旧包中寻找它。我就是这种情况。


C
Cameron Gagnon

除了 Thomas Kåsene 说的,还可以添加

@SpringBootTest(classes=com.package.path.class)

如果您不想重构文件层次结构,则添加到测试注释以指定它应该在哪里查找其他类。这就是错误消息所暗示的内容:

找不到@SpringBootConfiguration,需要使用@ContextConfiguration 或@SpringBootTest(classes=...) ...


h
hang gao

它对我有用

将上述测试类的包名改为与普通类的包名相同。

https://static.oschina.net/uploads/space/2018/0111/102730_tlKv_2885163.png

改成这个

https://static.oschina.net/uploads/space/2018/0111/103001_vJoi_2885163.png


N
Nick

在我的情况下,应用程序和测试类之间的包是不同的

package com.example.abc;
...
@SpringBootApplication
public class ProducerApplication {

package com.example.abc_etc;
...
@RunWith(SpringRunner.class)
@SpringBootTest
public class ProducerApplicationTest {

在让他们同意后,测试运行正确。


E
Enrico Giurin

我有同样的问题,我通过在文件夹 src/test/java 的根包中添加一个用 SpringBootApplication 注释的空类来解决

package org.enricogiurin.core;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class CoreTestConfiguration {}

没错,这正是我所寻找的,我有一个多模块弹簧项目,我将测试移至另一个模块,但只有这个类正确执行了该模块中的测试。
H
Hantsy

Spring Boot 1.4 中提供的测试切片带来了面向特征的测试能力。

例如,

@JsonTest 提供了一个简单的 Jackson 环境来测试 json 序列化和反序列化。

@WebMvcTest 提供了一个 mock 的 web 环境,它可以指定用于测试的控制器类并在测试中注入 MockMvc。

@WebMvcTest(PostController.class)
public class PostControllerMvcTest{

    @Inject MockMvc mockMvc;

}

@DataJpaTest 将准备一个嵌入式数据库并为测试提供基本的 JPA 环境。

@RestClientTest 为测试提供 REST 客户端环境,尤其是 RestTemplateBuilder 等。

这些注解不是用 SpringBootTest 组成的,它们是由一系列的 AutoconfigureXXX 和一个 @TypeExcludesFilter 的注解组合而成的。

看看@DataJpaTest

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@BootstrapWith(SpringBootTestContextBootstrapper.class)
@OverrideAutoConfiguration(enabled = false)
@TypeExcludeFilters(DataJpaTypeExcludeFilter.class)
@Transactional
@AutoConfigureCache
@AutoConfigureDataJpa
@AutoConfigureTestDatabase
@AutoConfigureTestEntityManager
@ImportAutoConfiguration
public @interface DataJpaTest {}

您可以添加 @AutoconfigureXXX 注释以覆盖默认配置。

@AutoConfigureTestDatabase(replace=NONE)
@DataJpaTest
public class TestClass{
}

来看看你的问题

不要混合使用@DataJpaTest 和@SpringBootTest,如上所述,@DataJpaTest 将从应用程序配置继承中以自己的方式构建配置(例如,默认情况下,它将尝试准备嵌入的 H2)。 @DataJpaTest 被指定用于测试切片。如果您想自定义@DataJpaTest 的配置,请阅读 Spring.io 的这篇官方博客文章(有点乏味)。按功能将应用程序中的配置拆分为更小的配置,例如 WebConfig、DataJpaConfig 等。功能齐全的配置(混合 Web、数据、安全等)也会导致基于测试切片的测试失败。检查我的样本中的测试样本。


k
kaybee99

当所有类都在同一个包中时,测试类正在工作。一旦我将所有 java 类移动到不同的包以维护正确的项目结构,我就会遇到同样的错误。

我通过在下面的测试类中提供我的主类名称来解决它。

@SpringBootTest(classes=JunitBasicsApplication.class)

a
ahmednabil88

在我的情况下
确保您的 YourApplicationTests 的 (test package 名称) 与 (main package 名称) 相同。


谢谢,我已经更改了应用程序的包名,但测试类的包仍然过时。
s
silver

我认为这个问题的最佳解决方案是将测试文件夹结构与应用程序文件夹结构对齐。

我遇到了同样的问题,这是由于从不同的文件夹结构项目中复制我的项目引起的。

如果您的测试项目和您的应用程序项目将具有相同的结构,您将不需要向您的测试类添加任何特殊注释,并且一切都会按原样工作。


我遇到了同样的错误,我终于发现测试类的包名称有一个拼写错误的“规则”而不是“规则”。修复包名称后,错误消失了。
M
Michal Lonski

这更多的是错误本身,而不是回答原始问题:

我们正在从 java 8 迁移到 java 11。应用程序编译成功,但是当使用 maven 从命令行运行时,错误 Unable to find a @SpringBootConfiguration 开始出现在集成测试中(从 IntelliJ 运行)。

maven-failsafe-plugin 似乎停止查看类路径上的类,我们通过告诉故障安全插件手动包含这些类来解决这个问题:

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-failsafe-plugin</artifactId>
            <configuration>
                <additionalClasspathElements>
                    <additionalClasspathElement>${basedir}/target/classes</additionalClasspathElement>
                </additionalClasspathElements>
            </configuration>
            ...
        </plugin>

h
happy

在我的情况下,我使用了错误包中的 Test 类。当我用 import org.junit.jupiter.api.Test; 替换 import org.junit.Test; 时,它起作用了。


E
Edor Linus

确保测试类位于主 Spring Boot 类的子包中


将此添加为评论
U
Umesh G
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureWebMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;



@RunWith(SpringRunner.class)
@DataJpaTest
@SpringBootTest
@AutoConfigureWebMvc
public class RepoTest {

    @Autowired
    private ThingShiftDetailsRepository thingShiftDetailsRepo;

    @Test
    public void findThingShiftDetails() {
            ShiftDetails details = new ShiftDetails();
            details.setThingId(1);

            thingShiftDetailsRepo.save(details);

            ShiftDetails dbDetails = thingShiftDetailsRepo.findByThingId(1);
            System.out.println(dbDetails);
    }
}

以上注释对我来说效果很好。我正在使用带有 JPA 的弹簧靴。