我想测试私有方法的行为。 方法“moveDataToArchive”执行4个步骤。
它是4x:计算日期+调用子方法。
这是我的测试:
@Test
public void testMoveData2Archive() throws Exception{
final long now = 123456789000L;
//Necessary to make the archivingBean runable.
Vector<LogEntry> logCollector = new Vector<LogEntry>();
Deencapsulation.setField(archivingBean, "logCollector", logCollector);
new NonStrictExpectations(archivingBean) {
{ //Lets fake the DB stuff.
invoke(archivingBean, "getConnection");result = connection;
connection.prepareStatement(anyString); result = prepStatement;
prepStatement.executeUpdate(); returns(Integer.valueOf(3), Integer.valueOf(0), Integer.valueOf(3));
}
};
new NonStrictExpectations(props) {
{ //This is important. The numbers will be used for one of each 4 submethods
props.getProperty(ArchivingHandlerBean.ARCHIVING_CREDMATURITY_OVER_IN_DAYS); result = "160";
props.getProperty(ArchivingHandlerBean.ARCHIVING_CREDHIST_AGE_IN_DAYS); result = "150";
props.getProperty(ArchivingHandlerBean.ARCHIVING_DEBTHIST_AGE_IN_DAYS); result = "140";
props.getProperty(ArchivingHandlerBean.ARCHIVING_LOG_AGE_IN_DAYS); result = "130";
}
};
new Expectations() {
{
Date expected = new Date(now - (160 * 24 * 60 * 60 * 1000));
invoke(archivingBean, "moveCreditBasic2Archive", expected);
expected = new Date(now - (150 * 24 * 60 * 60 * 1000));
invoke(archivingBean, "moveCreditHistory2Archive", expected);
expected = new Date(now - (999 * 24 * 60 * 60 * 1000));
invoke(archivingBean, "moveDebtorHistory2Archive", expected);
expected = new Date(now - (130 * 24 * 60 * 60 * 1000));
invoke(archivingBean, "moveLog2Archive", expected);
}
};
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(now);
Deencapsulation.invoke(archivingBean,"moveDataToArchive",cal, props);
}
问题是什么?查看第三个预期日期。这是错误的! (999而不是140)。 我也改变了电话的顺序。我甚至将这些私人方法公开并尝试了。所有这些变化都没有改变结果:测试是绿色的。
这里有什么问题?为什么测试是绿色的?
答案 0 :(得分:0)
测试是滥用模拟API,通过对同一个模拟(archivingBean
)混合严格和非严格的期望。记录在这个模拟上的第一个期望是非严格的,所以JMockit认为它是整个测试的非严格模拟。
编写测试的正确方法是在测试结束时将严格期望块(具有4次调用的块“子方法”)转换为验证块。 / p>
(另外,整个测试有几个问题.1)一般来说,私有方法应该通过一些公共方法间接测试。 2)此外,私有方法不应该被嘲笑,除非有强烈的理由否则 - 在这种情况下,我可能会编写一个测试来验证输出文件的实际内容。 3)不要不必要地嘲笑事物,例如我可以使用props
- props.setProperty
代替。 4)使用自动装箱 - Integer.valueOf(3)
- &gt; 3
)。
答案 1 :(得分:0)
@罗杰里奥: 你的假设不能完全奏效。即我没有setProperty()。我尝试的是使用Verifications-Block。
可悲的是,我不明白JMockit足以让它运行......
我做了两件事。首先,我试图模拟4个私有方法。我只想知道他们是否被召唤。但我不希望有逻辑运行。 我通过扩展第一个NonStrictExpectations-Block来尝试它:
new NonStrictExpectations(archivingBean) {
{
invoke(archivingBean, "getConnection");result = connection;
connection.prepareStatement(anyString); result = prepStatement;
prepStatement.executeUpdate(); returns(Integer.valueOf(3), Integer.valueOf(0), Integer.valueOf(3));
//New part
invoke(archivingBean, "moveCreditBasic2Archive", withAny(new Date()));
invoke(archivingBean, "moveCreditHistory2Archive", withAny(new Date()));
invoke(archivingBean, "moveDebtorHistory2Archive", withAny(new Date()));
invoke(archivingBean, "moveLog2Archive", withAny(new Date()));
}
};
另一方面,我将Expectations-Block向下移动并将其作为验证块。现在JUnit失败并带有
mockit.internal.MissingInvocation: Missing invocation of:
de.lpm.ejb.archiving.ArchivingHandlerBean#moveCreditBasic2Archive(java.util.Date pOlderThan)
with arguments: Tue Feb 03 03:39:51 CET 2009
on mock instance: de.lpm.ejb.archiving.ArchivingHandlerBean@1601bde
at de.lpm.ejb.archiving.ArchivingHandlerBean.moveCreditBasic2Archive(ArchivingHandlerBean.java:175)
[...]
Caused by: Missing invocation
这是ArchivingHandlerBean.java中的第170-175行:
170: Connection connection = getConnection();
171: SQLService service = new SQLService(connection);
172:
173: PreparedStatement prepStmtMove = null;
174:
175: Vector<HashMap<String, String>> where_clauses = new Vector<HashMap<String,String>>();
我只想验证4个私有方法是否使用正确的日期执行。