Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/383.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 编辑并重新运行spring引导单元测试,而无需重新加载上下文以加快测试速度_Java_Spring Boot_Unit Testing_Junit - Fatal编程技术网

Java 编辑并重新运行spring引导单元测试,而无需重新加载上下文以加快测试速度

Java 编辑并重新运行spring引导单元测试,而无需重新加载上下文以加快测试速度,java,spring-boot,unit-testing,junit,Java,Spring Boot,Unit Testing,Junit,我有一个SpringBoot应用程序,并使用postgres测试容器()和JUnit编写了单元测试。测试具有@SpringBootTest注释,该注释在运行测试之前加载上下文并启动测试容器 在我比较旧的Macbook上加载上下文和启动容器大约需要15秒,但是测试本身非常快(每个都

我有一个SpringBoot应用程序,并使用postgres测试容器()和JUnit编写了单元测试。测试具有@SpringBootTest注释,该注释在运行测试之前加载上下文并启动测试容器

在我比较旧的Macbook上加载上下文和启动容器大约需要15秒,但是测试本身非常快(每个都<100毫秒)。因此,在一个包含100个测试的完整构建中,这并不重要。这是15秒的一次性成本。 但是在IDE中单独开发/调试测试变得非常缓慢。每次测试都会产生15秒的启动成本


我知道IntelliJ和Springboot支持在应用程序运行时热重新加载类。对于单元测试,是否有类似的解决方案/建议?i、 e保持上下文加载和testcontainer(DB)运行,但只重新编译修改后的测试类并再次运行选定的测试。

我无法想象测试中会出现热重新加载的神奇标志-有太多的东西会弄脏spring上下文、弄脏数据库等

在我看来,这里最容易做的事情是用manual container start本地替换测试容器初始值设定项,并更改数据库的属性以指向该容器。如果您希望实现自动化,您可以添加启动前脚本(如果您使用IntelliJ…)来执行类似操作:
docker start postgres | | docker run postgres
(linux),如果容器未运行,它将启动容器,如果容器正在运行,则不执行任何操作


通常IDE重新编译只是更改受影响的类,如果没有容器启动,Spring上下文可能不会启动15秒,除非您还有很多bean要配置…

我正在尝试学习使用Spring Boot进行测试,如果这个答案不相关,那么很抱歉

我发现这表明了(按使用最多到最少的顺序)的组合:

  • Mockito使用@Mock注释进行单元测试,如果可能的话,不使用Spring上下文
  • 当您想要涉及一些Spring上下文时,使用@WebMvcTest注释对测试进行切片
  • 当您希望涉及整个Spring上下文时,使用@SpringBootTest注释进行集成测试

我认为您无法加载上下文

您可以从testcontainers中激活可重用容器功能。它可以防止测试运行后容器被破坏

您必须确保您的测试是幂等的,或者在完成后删除对容器所做的所有更改

简而言之,您应该将.withReuse(true)添加到容器定义中,并将testcontainers.reuse.enable=true添加到~/.testcontainers.properties(这是homedir中的一个文件)

下面是我如何定义testcontainer来使用Oracle测试代码

import org.testcontainers.containers.BindMode;
导入org.testcontainers.containers.OracleContainer;
公共类StaticOracleContainer{
公共静态OracleContainer getContainer(){
返回LazyOracleContainer.ORACLE_CONTAINER;
}
私有静态类LazyOracleContainer{
私有静态最终OracleContainer ORACLE_CONTAINER=makeContainer();
私有静态OracleContainer makeContainer(){
最终OracleContainer=新OracleContainer()
//testcontainers将使用的用户名
//了解容器是否已启动并正在运行
.withUsername(“系统”)
//testcontainers将要使用的密码
//了解容器是否已启动并正在运行
.withPassword(“123”)
//告诉testcontainers,这些端口应该
//将映射到外部端口
.带有暴露端口(15215500)
//Oracle数据库将不会启动,如果
//超过1gb的共享内存可用,因此这是必要的
.带有共享内存大小(2147483648L)
//这与给出容器相同
//-v/path/to/init_db.sql:/u01/app/oracle/scripts/startup/init_db.sql
//容器启动后,Oracle将执行init_db.sql
.withClasspathResourceMapping(“init_db.sql”
,“/u01/app/oracle/scripts/startup/init_db.sql”
,BindMode.只读)
//不要破坏容器
.withReuse(真)
;
container.start();
返回容器;
}
}
}
正如你所看到的,这是一个单身汉。我需要它来手动控制testcontainers生命周期,这样我就可以使用可重用容器了 如果您想知道如何使用此单例将Oracle添加到Spring测试上下文中,可以看看我使用testcontainers的示例


不过,这种方法有一个问题。Testcontainers永远不会停止可重用容器。您必须手动停止并销毁容器。

我相信有一个简单的解决方案可以解决您的问题。您尚未指定如何在测试中运行测试容器,但我有以下方法的成功经验:

对于在本地运行的测试,在笔记本电脑上启动一次postgres服务器(比如在工作日开始时)。它可以是停靠进程,甚至是常规postgresql安装

在测试期间,spring引导应用程序并不真正知道它与测试容器交互——它获取主机/端口/凭据,就这样——它使用这些参数创建了一个数据源

因此,对于本地开发,您可以修改与测试的集成
@Configuration
@ConditionalOnProperty(name = "test.local.mode", havingValue = "true", matchIfMissing = false)
public class MyDbConfig {
    @Bean
    public DataSource dataSource () {
      // create a data source initialized with local credentials
    }

}
spring:
  main:
    lazy-initialization: true