这似乎是关于Easymock的一个非常详细的问题,但我很难找到这个库的支持站点/论坛/邮件列表。
我在使用captures()
方法时遇到了一个错误,该方法似乎无法按顺序返回捕获的参数。
以下是我正在测试的简化版本:
public class CaptureTest extends TestCase {
// interface we will be mocking
interface Processor {
void process(String x);
}
// class that uses the interface above which will receive the mock
class Component {
private Processor processor;
private String[] s = { "one", "two", "three", "four" };
Component(Processor processor) {
this.processor = processor;
}
public void doSomething() {
for (int i = 0; i < s.length; i++) {
processor.process(s[i]);
}
}
}
public void testCapture() {
//create the mock, wire it up
Processor mockProcessor = createMock(Processor.class);
Component component = new Component(mockProcessor);
//we're going to call the process method four times
//with different arguments, and we want to capture
//the value passed to the mock so we can assert against it later
Capture<String> cap1 = new Capture<String>();
Capture<String> cap2 = new Capture<String>();
Capture<String> cap3 = new Capture<String>();
Capture<String> cap4 = new Capture<String>();
mockProcessor.process(and(isA(String.class), capture(cap1)));
mockProcessor.process(and(isA(String.class), capture(cap2)));
mockProcessor.process(and(isA(String.class), capture(cap3)));
mockProcessor.process(and(isA(String.class), capture(cap4)));
replay(mockProcessor);
component.doSomething();
//check what values were passed to the mock
assertEquals("one", cap1.getValue());
assertEquals("two", cap2.getValue());
assertEquals("three", cap3.getValue());
assertEquals("four", cap4.getValue());
verify(mockProcessor);
}
}
(请注意,这只是一个简化的测试用例 - 我知道我可以指定我希望传递给我的mock的参数的确切值,但在我的实际情况中,参数是带有少量字段的复杂对象,并且我想捕获对象,这样我就可以断言这几个字段,而无需在我的测试用例中重新创建整个对象。)
当我运行测试时,它失败了:
junit.framework.ComparisonFailure:expected:&lt; [one]&gt;但是:&lt; [4]&gt;
意味着EasyMock在cap1
中捕获的参数不是对方法的第一次调用,而是最后一次调用(因为值为four
)。如果我反转captures()
声明,即在第一次方法调用时使用cap4
等,我会得到相同的结果。
这似乎可能是EasyMock中的一个错误 - 在不同的调用中传递给同一方法的不同参数似乎无法正确捕获。
是否有其他人使用capture()
使用EasyMock并遇到类似问题?是否有一个你知道的简单解决方法,或者我可以采用不同的方式捕获传递给我的mock方法的参数?
更新1 :固定代码示例以显示我正在使用createMock
,而不是createStrictMock
,但我得到了同样的错误(尽管实际值是什么捕获的变化)。
答案 0 :(得分:4)
我收到了an answer关于我提交给Easymock sourceforge网站的错误,并且开发人员已经确认这确实是此版本的Easymock的错误。
这确实是一个错误。即使已经完成捕获也已完成。该 当前的解决方法是实现自己的捕获对象并覆盖 setValue执行此操作:
@Override
public void setValue(T value) {
if(!hasCaptured()) {
super.setValue(value);
}
}
答案 1 :(得分:1)
我正在玩你的测试但无法解决。 但是我扩展了Capture类以查看值是否以不同的顺序设置(我怀疑EasyMock内部使用的哈希与方法和参数生成的密钥)我错了方法设置正确的顺序。但是有一些非常奇怪的事情......似乎算法做了某种分配模式..让我展示代码和奇怪的输出......顺便说一句,来自mock,niceMock和strictMock的变化没有做出任何差异..
class MyCapture extends Capture<String> {
private String id;
public MyCapture(String id) {
super();
System.out.printf("Constructor %s expecting %s\n", id, this.getClass().getName());
this.id = id;
}
private static final long serialVersionUID = 1540983654657997692L;
@Override
public void setValue(String value) {
System.out.printf("setting value %s expecting %s \n", value, id);
super.setValue(value);
}
@Override
public String getValue() {
System.out
.printf("getting value %s expecting %s \n", super.getValue(), id);
return super.getValue();
}
}
public void testCapture() {
// create the mock, wire it up
Processor mockProcessor = createStrictMock(Processor.class);
Component component = new Component(mockProcessor);
// we're going to call the process method four times
// with different arguments, and we want to capture
// the value passed to the mock so we can assert against it later
Capture<String> cap1 = new MyCapture("A");
Capture<String> cap2 = new MyCapture("B");
Capture<String> cap3 = new MyCapture("C");
Capture<String> cap4 = new MyCapture("D");
mockProcessor.process(and(isA(String.class), capture(cap1)));
mockProcessor.process(and(isA(String.class), capture(cap2)));
mockProcessor.process(and(isA(String.class), capture(cap3)));
mockProcessor.process(and(isA(String.class), capture(cap4)));
replay(mockProcessor);
component.doSomething();
// check what values were passed to the mock
assertEquals("A", cap1.getValue());
assertEquals("B", cap2.getValue());
assertEquals("C", cap3.getValue());
assertEquals("D", cap4.getValue());
verify(mockProcessor);
}
}
*这是输出*
Constructor A expecting com.comp.core.dao.impl.CaptureTest$MyCapture
Constructor B expecting com.comp.core.dao.impl.CaptureTest$MyCapture
Constructor C expecting com.comp.core.dao.impl.CaptureTest$MyCapture
Constructor D expecting com.comp.core.dao.impl.CaptureTest$MyCapture
calling process A
setting value A expecting A
calling process B
setting value B expecting A <<Setting the wrong guy
setting value B expecting A <<Setting the wrong guy
setting value B expecting B <<Ops this is the right one..stop
calling process C
setting value C expecting B <<Setting the wrong guy
setting value C expecting B <<Setting the wrong guy
setting value C expecting C <<Setting the wrong guy
calling process D
setting value D expecting C <<Setting the wrong guy
setting value D expecting C <<Setting the wrong guy
setting value D expecting D <<Ops this is the right one..stop
getting value B expecting A
抱歉,我无法帮到你。它可能确实是一个容易模拟的错误。
答案 2 :(得分:0)
您也可以尝试使用EasyMock.createNiceMock(...)代替EasyMock.createStrictMock(...)或EasyMock.createMock(...)。
虽然,我同意它看起来更像是createMock的错误。
答案 3 :(得分:0)
我认为这是一个更适合基于状态的测试的问题。 使用JMockit,您可以像这样解决它:
import mockit.*;
import static mockit.Mockit.*;
import mockit.integration.junit3.*;
public class CaptureTest extends JMockitTestCase
{
interface Processor { void process(String x); }
class Component
{
private final Processor processor;
private final String[] s = {"one", "two", "three", "four"};
Component(Processor processor) { this.processor = processor; }
public void doSomething()
{
for (String value : s) {
processor.process(value);
}
}
}
@MockClass(realClass = Processor.class)
static class MockProcessor
{
private final String[] expectedValues;
private int i;
MockProcessor(String... expectedValues) { this.expectedValues = expectedValues; }
@Mock
void process(String x)
{
assertEquals(expectedValues[i++], x);
}
}
public void testCapture()
{
Processor mockProcessor = setUpMock(new MockProcessor("one", "two", "three", "four"));
Component component = new Component(mockProcessor);
component.doSomething();
}
}
答案 4 :(得分:0)
简而言之,这对我有用:
MyClass myMock = EasyMock.createStrictMock(MyClass.class);
...
EasyMock.checkOrder(myMock, true); // before the capture and verify, not sure if it matters
...
Capture<MyArg> capturedArgs = new Capture<MyArg>();
expect(myMock.search(capture(capturedArgs))).andReturn(someRandomReturn);
PS:我使用的是EasyMock 3.0
答案 5 :(得分:-1)
不要调用 EasyMock.createStrictMock(...),而只需调用 EasyMock.createMock(...)。应该解决你的问题。