java 如何使用easymock Capture进行测试

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1826173/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 18:08:25  来源:igfitidea点击:

How to test with easymock Capture

javaunit-testingeasymock

提问by Nuno Furtado

I have the following code

我有以下代码

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

The registerNewRecord method calls the RecordDao insert method, and updateRecord calls the update method on the same DAO.

registerNewRecord 方法调用 RecordDao 插入方法,updateRecord 调用同一个 DAO 上的更新方法。

I have the following easymock code:

我有以下easymock代码:

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

Problem is since above rd the same instance of Record that was inserted is being updated, the insertRc Capture object is being updated too. So i cannot assert that the finished flag is set to false at insert time.

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

What am i doing wrong?

我究竟做错了什么?

回答by DoctorRuss

If the references within insertRCand updateRCboth refer to the same object rdand this is changed during the updatemethod, you will always see that the Recordobject has finished. However, you could test the first Captured object before the updatecall is made.

如果内引用insertRC,并updateRC都指向同一个对象rd,这是在改变update方法,你总是会看到,Record对象已经完成。但是,您可以在update调用之前测试第一个 Captured 对象。

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());

回答by Joe Daley

One idea is to clone the Record object when you capture it.

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

Implement a clone()method in your Record class, and then implement a custom Capture as follows:

clone()在你的 Record 类中实现一个方法,然后实现一个自定义的 Capture,如下所示:

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

And change your test code to use it:

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

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

If you can't implement clone()for some reason, your custom Capture class could just extract the information it needs (i.e. the Record finished flag) in the setValuemethod and store it.

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

回答by Gus

Captures are not the answer. The problem is that your code is creating a new object in the registerNewRecord (or so I presume). There is no way to get the object you create with newbefore the code you are testing completes. Captures allow you to ask questions of an object created/obtained during execution, AFTER the method under test completes.

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

Another problem with your test is that your test for the current method depends on the code in the registerNewRecord()method and probably any code in the constructor of the Record object. One way to break this dependency and validate the intermediate state of the Record object is to stub out the registerNewRecord()method and have it return a mock. Then you can test that the right calls were made to the Record object, and that your code behaves correctly for all possible return values from the record object.

您的测试的另一个问题是您对当前方法的测试取决于方法中的代码,registerNewRecord()并且可能是 Record 对象的构造函数中的任何代码。打破这种依赖性并验证 Record 对象的中间状态的registerNewRecord()一种方法是将方法存根并让它返回一个模拟。然后您可以测试是否对 Record 对象进行了正确的调用,并且您的代码对于来自 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
}

As a positive side effect, you will find that your test only breaks when there is something wrong with the code in the method you are testing and never breaks if the problem lies in Record's constructor or registerNewRecord. You will however want to write a second test for the registerNewRecord()method to ensure that it works properly.

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