我有一个Spring-Boot应用程序,其中在应用程序中设置了默认属性。属性文件在类路径(src/main/resources/application.properties)。

我想用测试中声明的属性覆盖JUnit测试中的一些默认设置。属性文件(src/test/resources/test. Properties)

我通常为我的Junit测试有一个专用的配置类,例如。

package foo.bar.test;

import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
@Import(CoreConfig.class)
@EnableAutoConfiguration
public class TestConfig {

}

我最初认为在TestConfig类中使用@PropertySource("classpath:test.properties")可以达到目的,但是这些属性不会覆盖应用程序。属性设置(参见Spring-Boot参考文档- 23。外部化配置)。

然后我尝试使用-Dspring.config.location=classpath:test。属性。这是成功的——但是我不想为每次测试执行都设置这个系统属性。因此我把它放在代码中

@Configuration
@Import(CoreConfig.class)
@EnableAutoConfiguration
public class TestConfig {

  static {
    System.setProperty("spring.config.location", "classpath:test.properties");
  }

}

不幸的是,这次也没有成功。

必须有一个简单的解决方案如何覆盖应用程序。使用test在JUnit测试中设置属性。我一定是忽略了这些特性


当前回答

使用

使用.yaml file-ending声明的属性 Spring-Boot 2.7 类路径中有多个.yaml文件

我注意到@TestPropertySource(位置)的优先级没有像使用.properties文件一样被应用。

我遇到的问题是,Spring一直在加载所有的.yaml属性(特别是那些来自产品的属性),并使用为prod指定的值覆盖用于测试的属性。

我们提出了通过指定我的应用程序测试来覆盖配置抓取机制的变通方法。Yaml作为唯一的属性使用如下:

@TestPropertySource(properties = "spring.config.location=classpath:/application-test.yaml")

其他回答

如果你真的想要/不得不使用System.setProperties(…),那么使用Junit扩展并注释测试类:

...
@ExtendWith(MyBeforeAllCallback.class)
public SomeTestClass ...

并使用回调函数的构造函数设置系统属性。

public MyBeforeAllCallback implements BeforeAllCallback {
    public MyBeforeAllCallback() {
        // wicket 9 workaround for java 17 / cglib issue.
        System.setProperty("wicket.ioc.useByteBuddy", "true");
        // ... whatever you want ...
        System.setProperty("whatever", "you need it badly");
    }
    void beforeAll(ExtensionContext context) {
        // ... empty
    }
}

如果你和我一样有同样的应用。src/main/resources和src/test/resources中的属性,你想知道为什么应用程序。属性不会覆盖应用程序。属性在你的主要资源,阅读…

简单的解释:

If you have application.properties under src/main/resources and the same application.properties under src/test/resources, which application.properties gets picked up, depends on how you are running your tests. The folder structure src/main/resources and src/test/resources, is a Maven architectural convention, so if you run your test like mvnw test or even gradlew test, the application.properties in src/test/resources will get picked up, as test classpath will precede main classpath. But, if you run your test like Run as JUnit Test in Eclipse/STS, the application.properties in src/main/resources will get picked up, as main classpath precedes test classpath.

您可以通过打开菜单栏查看运行>运行配置> JUnit > *your_run_configuration* >单击“显示命令行”。

你会看到这样的东西:

XXXbin\javaw.exe -ea -Dfile。编码= UTF-8 -classpath XXX \ workspace-spring-tool-suite-4-4 5。1 .发布project_name \ bin \玩; XXX \ workspace-spring-tool-suite-4-4 5。1 .发布project_name \ bin \测试;

你看到类路径xxx\main先出现,然后是xxx\test吗?对,这都是关于类路径的:-)

附注: 注意在启动配置中覆盖的属性(例如在Spring Tool Suite IDE中)优先于application.properties。

改变顺序:

现在,在Spring中一切都是可配置的。你可以改变构建类路径,让xxx\test先出现,然后是xxx\main。

简单地转到项目>属性> Java构建路径>顺序和导出,通过将任何测试文件夹放在前面来更改构建类路径顺序,例如:

就是这样!

更好的解决方案

一个更好的解决方案是在测试时激活src/test/resources/application-{profile}。属性(其中profile可以测试),例如在src/main/resources/application.properties中:

spring.profiles.active =测试

这更整洁,并让您完全控制在做什么时激活哪个配置文件。

Spring Boot自动加载src/test/resources/application。属性,如果使用以下注释

@RunWith(SpringRunner.class)
@SpringBootTest

重命名test。应用程序的属性。属性来利用自动配置。

如果您只需要加载属性文件(到环境中),您也可以使用下面的方法,如下所述

@RunWith(SpringRunner.class)
@ContextConfiguration(initializers = ConfigFileApplicationContextInitializer.class) 

[更新:覆盖测试的某些属性]

添加src /主/资源/ application-test.properties。 用@ActiveProfiles(“test”)注释测试类。

这将加载应用程序。属性,然后应用程序测试。根据这里定义的规则,将属性放入测试用例的应用程序上下文中。

演示- https://github.com/mohnish82/so-spring-boot-testprops

您还可以使用元注释来具体化配置。例如:

@RunWith(SpringJUnit4ClassRunner.class)
@DefaultTestAnnotations
public class ExampleApplicationTests { 
   ...
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@SpringApplicationConfiguration(classes = ExampleApplication.class)
@TestPropertySource(locations="classpath:test.properties")
public @interface DefaultTestAnnotations { }

如果您正在使用Spring 5.2.5和Spring Boot 2.2.6,并且希望只覆盖一些属性而不是整个文件。您可以使用新的注释:@DynamicPropertySource

@SpringBootTest
@Testcontainers
class ExampleIntegrationTests {

    @Container
    static Neo4jContainer<?> neo4j = new Neo4jContainer<>();

    @DynamicPropertySource
    static void neo4jProperties(DynamicPropertyRegistry registry) {
        registry.add("spring.data.neo4j.uri", neo4j::getBoltUrl);
    }
}