为啥在 Spring Boot 应用程序的 Junit 测试中应用程序属性中的属性不可用?

Posted

技术标签:

【中文标题】为啥在 Spring Boot 应用程序的 Junit 测试中应用程序属性中的属性不可用?【英文标题】:why properties from appliction.properties not available in Junit test in spring boot application?为什么在 Spring Boot 应用程序的 Junit 测试中应用程序属性中的属性不可用? 【发布时间】:2016-12-18 12:03:08 【问题描述】:

我有一个 Spring Boot 应用程序。我正在编写 Junit 测试。 我正在尝试从 application.properties(在 src/main/resources/application.properties 中定义)和在 AppConfig(src/main/java/hello/AppConfig.java)中配置的 Status bean 注入值。我看到 bean 是自动装配的(通过调试器它不为空)但未设置值。

这里是 application.properties

src/main/resources/application.properties

app.name=rest-service
app.version=1.0.0-SNAPSHOT

src/main/java/hello/AppConfig.java

@Configuration
public class AppConfig 

    @Value("$app.version")
    private String version;
    @Value("$app.name")
    private String name;


    @Bean
    public Status status()
        return new Status(name,version);
    


//Status 是一个简单的 pojo,带有 name 和 version 字段

src/test/java/hello/GreetingControllerTests.java

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@ContextConfiguration(classes=hello.TestConfig.class,hello.AppConfig.class)
@WebAppConfiguration
public class GreetingControllerTests 


    @Autowired
    Environment envi;

    @Autowired
    Status status;

    @Value("$app.name:notConfigured")
    String appName;

    private String env;

    @Before
    public void init()
        System.out.println(status.getName());
        System.out.println(appName);
        env=envi.getActiveProfiles()[0];
    

    @Test
    public void should_fail()
        if (env.equalsIgnoreCase("DEV"))
            assertThat(false).isFalse();
        
        if (env.equalsIgnoreCase("QA1"))
            System.out.println("failing the test");
            fail();
        
    

我在 init 方法中设置了调试器,发现 appNamestatus 设置了正确值的 bean 都没有被注入。虽然注入了状态 bean。只是没有设置值。

【问题讨论】:

你的Application类是什么样的? 您在 application.properties 中有一个未放置的字符。 app.version 没有 = @ShawnClark:修复没有帮助。你可以在这里查看代码。 bitbucket.org/SpringDevSeattle/gs-rest-service 【参考方案1】:

感谢您分享项目。它使工作变得更加容易。请查看我的拉取请求(使用 cmets)以了解我是如何完成这一切的。

https://bitbucket.org/SpringDevSeattle/gs-rest-service/pull-requests/4/updating-project-for-spring-boot-14/diff

* 更新 * 由于将一些旧的 Spring 注释与较新的注释混合,您的注释被覆盖。感谢spring-boot properties not @Autowired 将我指向基于谷歌搜索application.properties not being populated in the environment 的解决方案。

如果你看@SpringApplicationConfiguration

@ContextConfiguration(loader = SpringApplicationContextLoader.class)
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Deprecated
public @interface SpringApplicationConfiguration 

它实际上是由许多其他注解组成的。重要的是@ContextConfiguration。对于@SpringApplicationConfiguration,它使用一个加载器,该加载器正在扫描类路径以查找适当的配置文件以及要加载的组件(一个是将 application.properties 读取到环境中的东西)。在测试中,您使用声明覆盖该注释:

@ContextConfiguration(classes=hello.TestConfig.class,hello.AppConfig.class)

这会强制 Spring 仅加载 TestConfig 和 AppConfig 类,而不扫描任何其他配置文件。注释掉该注解并运行它将使测试通过,调试 init() 方法将显示注入的值。

【讨论】:

感谢您花时间进行重构。我感谢你的努力。但我真的很想知道为什么我无法从 application.properties 注入值。如果你能帮忙,请做。我将合并您的拉取请求,但我确实想知道我哪里出错了。 我的拉取请求中的 cmets 解释了。 Spring Boot 1.4 改变了测试的运行方式。您可以看到您的注释已被弃用。我可以回去继续使用旧的 1.3 注释并尝试使其工作,但看到您已经为 1.4 设置了项目,我想我会向您展示如何利用新的东西。 找到了问题...更新了答案,因为我不能在这里全部输入。 很棒的发现。谢谢。但我只有两个配置类(AppConfig 和 TestConfig)。所以扫描它们应该足够正确吗?如果我想扫描额外的 TestConfig 以覆盖 AppConfig 的 bean 定义以进行测试.. 在 Spring 中,它不仅仅与您的 @Configuration 类有关。根据类路径中可用的内容,还有许多其他的东西是auto configured。对于您想要通过执行 @SpringApplicationConfiguration(classes = TestConfig.class ) 之类的操作来覆盖 @SpringApplicationConfiguration 仍然可能的事情的情况@​​【参考方案2】:

您需要测试下的资源目录中的另一个属性文件。

/src/test/resources

这就是junit正在寻找的地方。

【讨论】:

默认命名为application-test.properties。如果你想使用不同的名字,你也需要使用@TestPropertySource 如果我有不同的配置文件,例如 application-dev.properties,我是否需要在 src/test/resources 中有 application-dev-test.propeties? 对了,我在 src/test/resources 中添加了 application-test.properties 仍然没有看到注入的值? 试试 application.properties 我试过了。它也没有工作。你可以在这里浏览代码。 bitbucket.org/SpringDevSeattle/gs-rest-service/src/…

以上是关于为啥在 Spring Boot 应用程序的 Junit 测试中应用程序属性中的属性不可用?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 spring-boot 应用程序无法在 AWS 中运行,但在本地运行良好?

为啥我在 Spring-boot 应用程序中通过 SessionFactory 有循环依赖?

为啥 DataSource 不能在 Spring Boot 应用程序中自动装配?

为啥我的基本 Spring Boot 应用程序在构建后立即崩溃?

为啥在启动 Spring Boot 应用程序时出现 Gson builder 错误?

为啥我的 Spring Boot 应用程序出现异常?