如何测试只修改私有类成员变量的void方法?

Jam*_*win 7 java unit-testing

我正在尝试在一个初始化一些私有字段的类中对一个方法进行单元测试:

public void init(Properties props) throws Exception {

    this.language = props.getProperty(Constants.LANGUAGE,Constants.LANGUAGE_DEFAULT);   
    this.country = props.getProperty(Constants.COUNTRY,Constants.COUNTRY_DEFAULT);

        try {
            this.credits = Integer.valueOf(props.getProperty(Constants.CREDITS_OPTION_NAME, Constants.CREDITS_DEFAULT_VALUE));
        } catch (NumberFormatException e) {
            throw new Exception("Invalid configuration: 'credits' does not contain a valid integer value.", e);
        }
        //rest of method removed for sake of simplicity
    }
Run Code Online (Sandbox Code Playgroud)

我的困境是我想断言语言,国家和信用字段是在调用init之后设置的,但它们是私有的,没有公共访问器方法.我看到有两种解决方案可用于测试:

  1. 制作访问私有字段的公共方法,然后在测试init方法后调用这些方法.
  2. 使单元测试只调用init方法,并假设一切正常工作都没有抛出异常.

您认为测试此方法的理想方法是什么?

Boz*_*zho 9

您可以使用反射来获取私有字段的值.例如:

Field field = YourClass.class.getDeclaredField("language");
field.setAccessible(true); //override the access restriction of it being private
field.get(yourObject);
Run Code Online (Sandbox Code Playgroud)

如果你的类路径上有弹簧,你可以使用它的ReflectionUtils/ ReflectionTestUtils.

有时人们认为不应该验证私有字段,只有对象的公共状态才是单元测试的重点.从这个角度来看,暴露一个getter可能更好,甚至更好 - 抛出一个异常.

如果对象处于无效状态(如果未设置字段),则对象本身应负责通过抛出异常来强制其有效性.


Rae*_*ald 9

我想声明在调用init之后已经设置了语言,国家和信用字段

一些哲学:你为什么关心它们是否设置正确?如果答案是"所以该类的行为正确",那么您可以通过测试预期的后续行为来测试它们是否已设置正确.但是,如果设置不正确无效,则它们是多余的,您应该删除它们.

另一张海报建议使用反射来访问私人领域.我建议不要这样做; 标记为private的任何内容都应该是该类的实现细节,因此不应直接测试.您应该测试您的类的已发布API.然后,您可以通过更改实现(私有)详细信息,轻松地自由地重构它.