Mockito:验证调用捕获的对象的方法

时间:2015-12-02 13:46:59

标签: unit-testing junit mockito

我正在使用Mockito编写一个简单的单元测试。我有一个smiple abstract 类,它实现了Runnable

public abstract class MyRunnable implements Runnable {
  @Override
  public void run() {
    doTask();
  }
  public abstract void doTask();
}

然后,正在测试的函数使用MyRunnable

public class MyService {
  public void something() {
     executor.execute(new MyRunnable() {
        @Override
        doTask() {
          …
        }
     });
  }
}

我的测试用例,我想测试doTask()已运行:

@Test
public void testSomething() {
   …
   ArgumentCaptor<MyRunnable> myCaptor = ArgumentCaptor.forClass(MyRunnable.class);
   verify(mockMyService).something(myCaptor.capture());

   // get what has been captured
   MyRunnable myRunnable = myCaptor.getValue();
   //verify doTask() has run , but got ERROR.
   verify(myRunnable).doTask();
}

我的测试用例会抛出以下错误:

org.mockito.exceptions.misusing.NotAMockException: 
Argument passed to verify() is of type  and is not a mock!

错误抱怨verify()只接受模拟对象。那么,如何验证/测试捕获的 MyRunnable对象是否与Mockito一起运行doTask()

2 个答案:

答案 0 :(得分:1)

如果您可以控制代码库,则可以通过将使用new关键字的任何代码移动到单独的Factory类中来使Mockito使代码可以测试...

public class MyService {

  private MyRunnableFactory = factory;

  public MyService(MyRunnableFactory factory) {
    this.factory = factory;
  }

  public void something() {
     executor.execute(factory.createInstance());
  }
}

然后你的测试可以简单地注入工厂的模拟,你可以verify它的行为/交互

@Mock MyRunnableFactory factory;
@Mock MyRunnable myRunnable;

@Test
public void testSomething() {

   when(factory.createInstance()).thenReturn(myRunnable);

   // method under test
   MyService service = new MyService();
   service.something();

   verify(myRunnable).doTask();
}

我使用经验法则,创建对象的类不应该有任何业务逻辑,因此您不会遇到这些测试问题。这基本上是Single Responsibilty Principal

答案 1 :(得分:0)

您无法通过Mockito执行此操作,因为MyRunnable是由待测代码创建的。但你可以查看PowerMock因为它允许你模拟构造函数:https://github.com/jayway/powermock/wiki/MockConstructor