java 在 Spring 中使用 Mockito 模拟属性文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6388655/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Mocking a Properties file with Mockito in Spring
提问by blong824
I am trying to write a unit test for the following method in my controller.
我正在尝试在我的控制器中为以下方法编写单元测试。
@Autowired
private ApplicationContext context;
private String getProperty() {
try {
Properties props = context.getBean("myProperties", Properties.class);
String val = props.getProperty("myProperty");
......
The Bean is declared like this in my applicationContext:
Bean 在我的 applicationContext 中是这样声明的:
<util:properties id="myProperties" scope="prototype" location="file:${catalina.base}/webapps/myProperties.properties"/>
How can I mock this so that I can test different values of the val variable?
我如何模拟这个以便我可以测试 val 变量的不同值?
I thought about creating a test properties file and mocking it like this:
我想过创建一个测试属性文件并像这样模拟它:
context = Mockito.mock(ApplicationContext.class);
Mocikto.when(context.getBean("myProperties", Properties.class)).thenReturn(some test file)
but then I would have to declare the test file as a bean somewhere.
但是我必须在某处将测试文件声明为 bean。
I was wondering if there was an easier way to do this?
我想知道是否有更简单的方法来做到这一点?
Thanks
谢谢
采纳答案by Kevin
If you're using spring-3, you can do:
如果您使用的是 spring-3,则可以执行以下操作:
<context:property-placeholder location="myprops.properties" />
And in your code:
在你的代码中:
@Value("${myProperty}")
private String myProp;
public String getMyProp() {
return myProp;
}
This causes myprops.properties to be made available for variable substitutions via ${...} expressions, and the @Value annotation allows value injection of properties. Then in your unit test you can simply set different values of myProp.
这导致 myprops.properties 可用于通过 ${...} 表达式进行变量替换,并且 @Value 注释允许属性的值注入。然后在您的单元测试中,您可以简单地设置 myProp 的不同值。
回答by Brad
So I can test without having to load the Spring Context I use a Config class for accessing all of the properties file(s) values from within code. The benefits are:
所以我可以测试而不必加载 Spring Context 我使用 Config 类从代码中访问所有属性文件值。好处是:
1) Spring doesn't load in your unit tests
1) Spring 不会加载到您的单元测试中
2) You can force an Exception if the property is missing and it is required
2) 如果该属性缺失并且是必需的,您可以强制异常
3) You can return strongly type property values from the getter() methods (i.e. convert to a Date)
3) 您可以从 getter() 方法返回强类型属性值(即转换为日期)
4) The "key" values expected from your properties files are documented in a single Java class (i.e. public static final PROP_XXX)
4) 属性文件中预期的“键”值记录在单个 Java 类中(即 public static final PROP_XXX)
@Component
public class Config {
public static final String PROP_USER_NAME = "user.name";
private Properties applicationProperties;
/*** Functional methods ***/
/**
* Helper method to ensure consistent Exception handling where requested property values are missing
* from the properties files and they are "required" for the application to function correctly.
*
* @param key
* @return The String value of the property requested
*/
private String readPropertyRequired(String key) {
String value = readProperty(key);
if(StringUtils.isBlank(value)) {
throw new PropertyNotFoundException(key);
}
return value;
}
/**
* Helper method to return String values from the properties files that have been loaded
*
* @param key
* @return The String value of the property requested or NULL if empty
*/
private String readProperty(String key) {
return applicationProperties.getProperty(key);
}
/*** Getters & Setters ***/
@Autowired
public void setApplicationProperties(Properties applicationProperties) {
this.applicationProperties = applicationProperties;
}
public String getUserName() {
return readPropertyRequired(PROP_USER_NAME);
}
}
}
You can then unit test this class by simply injecting a standard java.util.Properties
然后,您可以通过简单地注入标准 java.util.Properties 来对此类进行单元测试
回答by Nathan Hughes
The easier way is to use a org.springframework.beans.factory.config.PropertyPlaceholderConfigurerinstead of pulling the properties explicitly from the spring application context. The PropertyPlaceholderConfigurer injects your bean with the properties you specify. Then you don't need Mockito at all, in the test you set the property value in the Controller to whatever you want it to be.
更简单的方法是使用org.springframework.beans.factory.config.PropertyPlaceholderConfigurer而不是从 spring 应用程序上下文中显式提取属性。PropertyPlaceholderConfigurer 将您指定的属性注入到您的 bean 中。那么你根本不需要 Mockito,在测试中你将 Controller 中的属性值设置为你想要的任何值。
So you'd set up the configurer in the application context xml:
因此,您将在应用程序上下文 xml 中设置配置器:
<context:property-placeholder
location="file:${catalina.base}/webapps/myProperties.properties"/>
and add some configuration for your controller (I expect there's a way to do this with annotations but don't know it):
并为您的控制器添加一些配置(我希望有一种方法可以使用注释来做到这一点,但不知道):
<bean id="whateverMyControllerIdIs" class="com.initech.foobar.MyControllerImpl">
<property name="quux"><value>${myProperty}</value></property>
</bean>
where the controller has an instance variable that you want to populate with the property, with a setter, like this:
其中控制器有一个实例变量,你想用属性填充它,用一个setter,像这样:
String quux;
public void setQuux(String quux) {this.quux = quux;}
Just saw a blog post on Spring 3.1 enhancements, here's the new xml-free way to do this:
刚刚看到一篇关于 Spring 3.1 增强功能的博客文章,这是一种新的 xml-free 方法:
@Configuration
@PropertySource("classpath:/com/myco/app.properties")
public class AppConfig {
@Autowired
Environment env;
@Bean
public TestBean testBean() {
TestBean testBean = new TestBean();
testBean.setName(env.getProperty("testbean.name"));
return testBean;
}
}