JUnit Easymock 意外的方法调用

Posted

技术标签:

【中文标题】JUnit Easymock 意外的方法调用【英文标题】:JUnit Easymock Unexpected method call 【发布时间】:2011-01-08 00:01:09 【问题描述】:

我正在尝试使用 EasyMock 在 JUnit 中设置测试,但遇到了一个小问题,我似乎无法解决这个问题。我希望这里有人可以提供帮助。

这是我正在尝试测试的方法的简化版本:

public void myMethod() 
    //(...)
    Obj myObj = this.service.getObj(param);
    if (myObj.getExtId() != null) 
      OtherObj otherObj = new OtherObj();
      otherObj.setId(myObj.getExtId());
      this.dao.insert(otherObj);
    
    //(...)

好的,我使用 EasyMock 模拟了 service.getObj(myObj) 调用,效果很好。

当 JUnit 调用 dao.insert(otherObj) 时,我的问题就出现了。 EasyMock 会在上面抛出一个*Unexpected Method Call*

我不介意在我的测试中嘲笑该 dao 并在其上使用 expectLastCall().once();,但这假设我在插入时作为参数传递的“otherObj”上有句柄...... 我当然不会,因为它是在被测试方法的上下文中有条件地创建的。

有没有人曾经处理过这个问题并以某种方式解决了它?

谢谢。

【问题讨论】:

【参考方案1】:

您还可以使用EasyMock.isA(OtherObj.class) 来提高类型安全性。

【讨论】:

【参考方案2】:

如果您无法在测试代码中获得对对象本身的引用,您可以使用EasyMock.anyObject() 作为insert 方法的预期参数。顾名思义,它会期望使用.. 任何对象调用该方法:)

它可能比匹配确切的论点不那么严格,但如果你对它感到满意,不妨试一试。请记住在声明预期的方法调用时包含对OtherObj的强制转换。

【讨论】:

【参考方案3】:

如果你只是想通过这个调用,anyObject() 匹配器非常有用,但如果你真的想验证构造的对象是你认为的那样,你可以使用 Capture。它看起来像:

Capture<OtherObj> capturedOtherObj = new Capture<OtherObj>();
mockDao.insert(capture(capturedOtherObj));
replay(mockDao);

objUnderTest.myMethod();

assertThat("captured what you expected", capturedOtherObj.getValue().getId(), 
           equalTo(expectedId));

此外,PowerMock 可以预期构造一个对象,因此如果需要,您可以查看它。

【讨论】:

【参考方案4】:

另请注意,如果您使用EasyMock.createStrictMock();,则方法调用的顺序也很重要,如果您违反此规则,则会引发意外的方法调用。

【讨论】:

以上是关于JUnit Easymock 意外的方法调用的主要内容,如果未能解决你的问题,请参考以下文章

如何嘲笑使用JUnit,EasyMock的或PowerMock静态final变量

使用easymock,重复void方法调用

测试没有使用 EasyMock 调用 void 方法

JSF - JUnit FacesContext模拟测试

Easymock:如何在不可见的情况下模拟受保护方法的调用

如何 EasyMock 对返回通配符泛型的方法的调用?