JMockit - 严格期望被忽略

时间:2013-06-25 10:04:08

标签: java junit mocking jmockit

我想测试私有方法的行为。 方法“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)。 我也改变了电话的顺序。我甚至将这些私人方法公开并尝试了。所有这些变化都没有改变结果:测试是绿色的。

这里有什么问题?为什么测试是绿色的?

2 个答案:

答案 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个私有方法是否使用正确的日期执行。