【问题标题】:Junit, Mockito, how to test a callbacks [duplicate]Junit,Mockito,如何测试回调[重复]
【发布时间】:2012-09-10 13:06:10
【问题描述】:

可能重复:
Intercept object on method invocation with Mockito

我有一个类可以从一种格式映射到另一种格式。由于这是遗留代码,我不敢重写它,它基本上是一组插件,所以如果我更改一个,我可能不得不更改所有其他。它的开发没有考虑到测试。 所以这是我的问题。

interface Mapper {
    void handle(ClassA classA);
    void handle(ClassB classB);
}

public interface Publisher {
    public void publish(MappedClass mappedClass);
}

class MyMapper implements Mapper {

    private Publisher publisher;
    public void setPublisher(final Publisher publisher) {
        this.publisher = publisher;
    }

    public handle(ClassA classA) {
        final MappedClass mappedClass = // Map from ClassA to MappedClass
        publisher.publish(mappedClass);
    }

    public handle(ClassB classB) {
        final MappedClass mappedClass = // Map from ClassB to MappedClass
        publisher.publish(mappedClass);
    }
}

好的。因此,取决于哪个类被“处理”MappedClass 将发布不同的值,这是我要验证的值(测试)。问题是我将得到一个测试,首先我必须编写代码来测试 publish 方法是否被调用,

private boolean wasCalled;

@Test
public void testClassAMapped() {
    wasCalled = false;
    final MyMapper myMapper = new MyMapper();
    myMapper.setPublisher(new Publisher() {
        public void publish(final MappedClass mappedClass) {
            wasCalled = true;
           // Code for verifying the fields in mappedClass
        });
    }
    final ClassA classA = // Create classA
    myMapper.handle(classA);
    assertTrue(wasCalled);
}

所以首先我们创建我们的模拟Publisher,它将首先将wasCalled 的状态设置为true,所以我们知道这个方法曾经被调用过(这个例子被简化了,所以代码中实际上有一个调度程序.. . 遗留代码,所以我不想更改它),其次我想验证MappedClass 具有正确的字段值。 我想知道的是,是否有人知道更好的测试方法? wasCalledwasCalled 检查成为我的许多测试的或多或少的样板代码,但由于我不想添加那么多混乱(自己的黑客、测试基类等)我想知道是否有没有办法在 Mockito 或 EasyMock 中做到这一点?

【问题讨论】:

    标签: java junit mockito easymock


    【解决方案1】:

    使用Mockito ArgumentCaptor

    @Test
    public void test(){
      Publisher publisher = Mockito.mock(Publisher.class);
      myMapper.setPublisher(publisher);
      ArgumentCaptor<MappedClass> captor = ArgumentCaptor.forClass(MappedClass.class);
    
      ....
      myMapper.handle(...);
      ...
    
      verify(publisher).publish(captor.capture());
      MappedClass passedValue = captor.getValue();
      // assert stuff here
    }
    

    【讨论】:

    • 酷。这实际上可能是我正在寻找的。谢谢。
    【解决方案2】:

    我不确定我是否完全理解这个问题,但看起来你正在寻找Mockito.verify(publisher).publish(Matchers.isA(MappedClass.class));

    为此,您必须模拟 Publisher
    Publisher publisher = Mockito.mock(Publisher.class)
    然后把它交给MyMapper

    如果您需要声明MappedClass 的状态,请使用ArgumentCaptor。示例见this answer

    Mockito-API-doc 有许多其他示例。

    【讨论】:

    • 问题只是我想摆脱 wasCalled 但仍然能够验证 MappedClass 中的字段是否正确,如果我模拟 Publisher.class 我将无法验证MappedClass 中的字段。我什至不知道是否有解决我的问题的方法,只是想问这个问题,看看有没有使用 Mockito 或 EasyMock 经验的人以前见过这个问题。
    • 正确填写字段重要吗?难道你不能检查一下行为是否符合你的期望吗?
    • 我已经修改了答案,让您开始使用 MappedClass 上的断言。
    • 是的,因为 MyWrapper 中有一个逻辑,它决定一个字段应该获得哪个值,具体取决于它是“发布”的 ClassA 还是 ClassB。我不知道在哪里可以测试这个。
    • 非常感谢您的帮助。 ArgumentCaptor 是解决方案。但是,我将下面的答案标记为正确。
    猜你喜欢
    • 2020-09-10
    • 2014-10-20
    • 2017-07-22
    • 2019-12-23
    • 1970-01-01
    • 2021-11-06
    • 2020-02-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多