【问题标题】:Mocking a Properties file with Mockito in Spring在 Spring 中使用 Mockito 模拟属性文件
【发布时间】:2011-09-17 08:02:28
【问题描述】:

我正在尝试在我的控制器中为以下方法编写单元测试。

@Autowired
    private ApplicationContext context;

    private String getProperty() {
        try {
            Properties props = context.getBean("myProperties", Properties.class);
            String val = props.getProperty("myProperty");
......

Bean 在我的 applicationContext 中是这样声明的:

<util:properties id="myProperties" scope="prototype" location="file:${catalina.base}/webapps/myProperties.properties"/>

我怎样才能模拟这个,以便我可以测试 val 变量的不同值?

我想过创建一个测试属性文件并像这样模拟它:

context = Mockito.mock(ApplicationContext.class);
Mocikto.when(context.getBean("myProperties", Properties.class)).thenReturn(some test file)

但是我必须在某处将测试文件声明为 bean。

我想知道是否有更简单的方法可以做到这一点?

谢谢

【问题讨论】:

  • 你在使用 Spring MVC 吗?您可以简单地在 Controller 上定义一个字段并在控制器的 bean 定义中为其设置一个值,而不是为您的控制器提供对 ApplicationContext 的引用并从中提取值。然后测试就不是问题了,因为您可以在测试中随意初始化控制器 - 根本不需要模拟应用程序上下文。

标签: java spring properties mockito


【解决方案1】:

如果你使用的是 spring-3,你可以这样做:

<context:property-placeholder location="myprops.properties" />

在你的代码中:

@Value("${myProperty}")
private String myProp;

public String getMyProp() {
    return myProp;
}

这导致 myprops.properties 可用于通过 ${...} 表达式进行变量替换,并且 @Value 注释允许属性的值注入。然后在您的单元测试中,您可以简单地设置不同的 myProp 值。

【讨论】:

  • 这与我之前提出的一个问题有关……如果找不到 myprops.proeprties 会怎样?目前我在 try catch 块中有这个,因为这个属性文件存在于战争之外,并且它有可能不在正确的位置
  • 弹簧容器会抛出。如果找不到属性,我想您可以尝试应用一些默认值,但我更喜欢不启动容器。如果属性文件丢失或位于错误的位置或其他地方,您是否宁愿立即找出并修复它,而不是默默地退回到一些可能不正确的属性?
  • 你把&lt;context:property-placeholder location="myprops.properties" /&gt; 放在哪里?
【解决方案2】:

更简单的方法是使用org.springframework.beans.factory.config.PropertyPlaceholderConfigurer,而不是从 spring 应用程序上下文中显式拉取属性。 PropertyPlaceholderConfigurer 使用您指定的属性注入您的 bean。那么你根本不需要 Mockito,在测试中你将 Controller 中的属性值设置为你想要的任何值。

所以你应该在应用程序上下文 xml 中设置配置器:

<context:property-placeholder 
  location="file:${catalina.base}/webapps/myProperties.properties"/>

并为您的控制器添加一些配置(我希望有一种方法可以使用注释但不知道):

 <bean id="whateverMyControllerIdIs" class="com.initech.foobar.MyControllerImpl">
   <property name="quux"><value>${myProperty}</value></property>
 </bean>

控制器有一个实例变量,你想用属性填充它,用一个setter,像这样:

String quux;

public void setQuux(String quux) {this.quux = quux;}

刚刚看到a blog post on Spring 3.1 enhancements,这是执行此操作的新的无 xml 方式:

    @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;
    }
}

【讨论】:

  • 感谢您的回复。你能用我上面的例子告诉我那个代码是什么样子的吗?
【解决方案3】:

所以我可以在无需加载 Spring 上下文的情况下进行测试,我使用 Config 类从代码中访问所有属性文件值。好处是:

1) Spring 不会加载到您的单元测试中

2) 如果该属性缺失并且是必需的,您可以强制异常

3) 您可以从 getter() 方法返回强类型属性值(即转换为日期)

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);
}

}

然后您可以通过简单地注入标准 java.util.Properties 来对此类进行单元测试

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-06-16
    • 1970-01-01
    • 1970-01-01
    • 2022-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多