我正在尝试对初始化某些私有字段的类中的方法进行单元测试:
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
}
我的困境是我想断言语言,国家和信用字段是在调用init之后设置的,但它们是私有的,没有公共访问器方法。我看到有两种解决方案可用于测试:
您认为测试此方法的理想方法是什么?
答案 0 :(得分:9)
您可以使用反射来获取私有字段的值。例如:
Field field = YourClass.class.getDeclaredField("language");
field.setAccessible(true); //override the access restriction of it being private
field.get(yourObject);
如果您的类路径中有弹簧,则可以使用其ReflectionUtils
/ ReflectionTestUtils
。
有时人们认为不应该验证私有字段,只有对象的公共状态才是单元测试的重点。从这个角度来看,暴露一个getter可能更好,甚至更好 - 抛出异常。
如果对象处于无效状态(如果未设置字段),则对象本身应负责通过抛出异常来强制执行其有效性。
答案 1 :(得分:9)
我想声明在调用init
之后设置了语言,国家和信用字段
一些哲学:你为什么关心它们是否设置正确?如果答案是“所以该类的行为正确”,那么您可以通过测试预期的后续行为来测试它们是否已经设置正确。但是,如果设置不正确无效,则它们是多余的,您应该删除它们。
另一张海报建议使用反射访问私有字段。我建议不要这样做;标记为private的任何内容都应该是该类的实现细节,因此不应直接测试。您应该测试您的类的已发布API。然后,您可以通过更改实现(私有)详细信息,轻松地自由地重构它。
答案 2 :(得分:4)
我通常会尝试避免依赖于被测试类的内部结构的测试。我更倾向于通过测试一些然后使用这些字段的方法来测试它。
如果您正在进行严格的TDD,那么在您拥有实际利用它们的测试用例之前,您甚至不应该添加这些字段:)
答案 3 :(得分:1)
您的JUnit是否直接调用该方法?然后对属性对象的引用是相同的,你应该能够访问语言和国家,以便在你的JUnit中重新计算。
私有方法的公共访问器也是一个不错的选择。
答案 4 :(得分:1)
就个人而言,我只会查看公共方法。有时您需要检查内部,但这种情况很少见。
BTW:公共getter的替代方案是在同一个包中进行单元测试并提供包本地getter。