如何使用easymock Capture进行测试

时间:2009-12-01 13:24:07

标签: java unit-testing easymock

我有以下代码

Record rd = registerNewRecord();
<do some processing>
rd.setFinished(true);
updateRecord(rd);

registerNewRecord方法调用RecordDao insert方法,updateRecord在同一个DAO上调用update方法。

我有以下easymock代码:

Capture<Record> insertRc = new Capture<Record>();
RecordDao.insert(capture(insertRc));
Capture<Record> updateRc= new Capture<Record>();
RecordDao.update(capture(updateRc));

问题是从上面开始,正在更新插入的Record的同一个实例,insertRc Capture对象也在更新。所以我不能断言在插入时将完成标志设置为false。

我做错了什么?

3 个答案:

答案 0 :(得分:3)

如果insertRCupdateRC中的引用都引用了同一个对象rd并且在update方法中进行了更改,那么您将始终看到Record 1}}对象已经完成。但是,您可以在update调用之前测试第一个捕获的对象。

Capture<Record> insertRc = new Capture<Record>();
RecordDao.insert(capture(insertRc));
Record insertedRecord = insertRC.getValue();
org.junit.Assert.assertFalse(insertedRecord.isFinished());

Capture<Record> updateRc= new Capture<Record>();
RecordDao.update(capture(updateRc));
Record updatedRecord = updateRC.getValue();
org.junit.Assert.assertTrue(updatedRecord.isFinished());

答案 1 :(得分:2)

一个想法是在捕获它时克隆Record对象。

在Record类中实现clone()方法,然后按如下方式实现自定义Capture:

public class RecordCloneCapture extends Capture<Record> {
    @Override
    public void setValue(Record value) {
        super.setValue(value == null ? null : value.clone());
    }
}

并更改您的测试代码以使用它:

Capture<Record> insertRc = new RecordCloneCapture();
RecordDao.insert(capture(insertRc));
Capture<Record> updateRc= new RecordCloneCapture();
RecordDao.update(capture(updateRc));

如果由于某种原因无法实现clone(),您的自定义Capture类可以在setValue方法中提取所需的信息(即Record finished标记)并存储它。

答案 2 :(得分:0)

捕获不是答案。问题是你的代码是在registerNewRecord中创建一个新对象(或者我认为是这样)。在您测试的代码完成之前,无法使用new获取您创建的对象。捕获允许您在测试方法完成后询问在执行期间创建/获取的对象的问题。

您的测试的另一个问题是您对当前方法的测试取决于registerNewRecord()方法中的代码以及Record对象的构造函数中的任何代码。打破这种依赖关系并验证Record对象的中间状态的一种方法是删除registerNewRecord()方法并让它返回一个模拟。然后,您可以测试对Record对象的正确调用,以及您的代码对记录对象的所有可能返回值的行为是否正确。

MyClassStub extends MyClass {
  Record registerNewRecord() {
    return recordMock;
  }
}

MyClass objectToTest = new MyClassStub();

public void testSomeMethod() {
   // set expectations, call replay
   objectToTest.someMethod();  // (contains above code that calls registerRecord)
   // asserts/verify
}

作为一个积极的副作用,您会发现只有当您正在测试的方法中的代码出现问题时,您的测试才会中断,如果问题出在Record的构造函数或registerNewRecord中,则永远不会中断。但是,您需要为registerNewRecord()方法编写第二个测试,以确保它正常工作。