【问题标题】:Overriding default Spring @Value annotation value in unit test在单元测试中覆盖默认的 Spring @Value 注释值
【发布时间】:2018-07-14 11:48:05
【问题描述】:

我正在尝试覆盖在测试类中具有默认值的 Spring @Value 注释属性。

@Configuration
public class MyConfig {
    @Value("${MAX_CONN:200}")
    private int maxConn;

    //more code here
}

@RunWith(SpringRunner.class)
@ContextConfiguration(classes={MyConfig.class, PropertySourcesPlaceholderConfigurer.class}, loader=AnnotationConfigContextLoader.class)
@TestPropertySource(properties = {
        "MAX_CONN=2"
})
public class SomeTest {
    //tests here
}

我为此目的使用了org.springframework.test.context.TestPropertySource 注释(thanks for the advise)。在调试过程中,我看到 maxConn 值仍然是 200。如果从原始代码 @Value("${MAX_CONN}") 中删除默认值,则 maxConn 值被 2 覆盖。 也可以通过定义环境变量来覆盖默认属性。 我想知道是否有办法覆盖具有默认值的@Value 注释属性?

注意:Spring 版本 - 4.3.13

【问题讨论】:

  • 你可以使用ReflectionTestUtils.setField()
  • @pvpkiran - 谢谢,我也是从link 学到的。我只是想知道是否有更优雅的方式。
  • 对于unit test,您不必初始化 Spring,以防您不进行测试。 Spring 特定:如数据库工作或 MVC。
  • @oleg.cherednik - 最后,使用 Mockito 和 ReflectionTestUtils 实现“无弹簧”单元测试。更多的代码,更少的时间,没有巫术
  • @anuta 但它在大型项目中节省了大量时间,Spring 团队在他们的文档中推荐了这种方法。

标签: java spring unit-testing


【解决方案1】:

以上运行配置的输出

MyConfig{maxConn=100}

Process finished with exit code 0

SpringBootWebApplication.java

package com.test;

import com.test.service.MyConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.Banner;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringBootConsoleApplication implements CommandLineRunner {

    @Autowired
    MyConfig myConfig;


    public static void main(String[] args) throws Exception {
        SpringApplication app = new SpringApplication(SpringBootConsoleApplication.class);
        app.setBannerMode(Banner.Mode.OFF);
        app.run(args);
        //SpringApplication.run(SpringBootConsoleApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        System.out.println(myConfig);
    }
}

MyConfig.java

package com.test.service;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class MyConfig {

    @Value("${MAX.CONN:200}")
    private int maxConn;

    @Override
    public String toString() {
        return "MyConfig{" +
                "maxConn=" + maxConn +
                '}';
    }
}

TestProperties.java

import com.test.SpringBootConsoleApplication;
import com.test.service.MyConfig;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringBootConsoleApplication.class)
public class TestProperties {

    static {
        System.setProperty("MAX.CONN", "2");
    }

    @Autowired
    MyConfig myConfig;

    @Test
    public void testSequence() {
        //System.out.println(myConfig);
        //...
    }

}

带有测试的输出:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.5.9.RELEASE)

MyConfig{maxConn=2}

Process finished with exit code 0

【讨论】:

  • 我已经在 Spring Boot 1.5.1 和 SpringFramework 4.3.6 上进行了尝试。让我用 Spring Boot 1.5.9 尝试同样的事情,它将使用 Spring Framework 4.3.13
  • 我们不使用属性文件,而是使用环境变量
  • @anuta 我已经更新了使用环境变量的答案。
  • 问题未解决,因为我需要在单元测试本身中以编程方式覆盖该属性。我决定不在问题的 cmets 中提到的单元测试中使用 spring。
  • @anuta 如果您在测试使用 spring 注释的代码期间没有使用 spring,那么从概念上讲,不会对代码进行全面覆盖测试。是的,您可以使用 powermock 和 mockito 进行测试,但不建议用于这种情况。
【解决方案2】:

对于在单元测试用例中使用属性,通常有两种方式,

1> 您应该拥有自己的一组用于测试的属性,并且文件应该位于您的类路径 (/src/test/resources) 下。

@PropertySource("classpath:application-test.properties ")

2> 另一个约定是在不同的类路径上拥有同名的属性文件。您加载一个或另一个取决于您是否正在运行测试。

因此,在一个典型布局的应用程序中,它是:

src/test/resources/application.properties

src/main/resources/application.properties

并将其用作

@PropertySource("classpath:application.properties ")

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-26
    • 2011-06-09
    • 2017-11-22
    相关资源
    最近更新 更多