通缉但未援引:Mockito和Retrofit

时间:2018-03-14 13:12:07

标签: unit-testing mockito retrofit2 android-testing

我正在尝试使用Mockito对我的api进行单元测试。 我看一下S.O已经提到的所有问题以及解决方案,但到目前为止,它们都没有定论。

MyService是一个包含多个资源的接口。这是一个示例:

public interface MyService {
@GET("/myresource")
Call<MyResponse> getDataFromServer();
}

在我的Application类中,我有一个返回MyService实例的静态类

public static MyService getApiService() {
    return mApiService;
}

所以,从我的一个班级里面,我打电话给网络服务:

Call<MyResponse> call = getApiService.getDataFromServer();
call.enqueue(myCallback)

其余的是调用回调方法....

这是我的测试类:

@RunWith(AndroidJUnit4.class)
public class SampleTest {

@Mock
private MyService mService;

@Captor
private ArgumentCaptor<Callback<MyResponse>> callbackArgumentCaptor;

@Mock
private Call<MyResponse> mockCall;

//  Rule to trigger the creation of @Mock annotated objects.
@Rule
public MockitoRule mockitoRule = MockitoJUnit.rule();

@Test
public void testDoAction() throws NullInsteadOfMockException {
    when(mService.doSomeAction()).thenReturn(mockCall);
    mService.doSomeAction();
    verify(mockCall).enqueue(callbackArgumentCaptor.capture());
    }
}

这是我运行测试后的错误:

Wanted but not invoked:
    mockCall.enqueue(
    <Capturing argument>
    );
    Actually, there were zero interactions with this mock.

即使使用MockitoJunitRunner(代替AndroidJunitRunner)我也有同样的错误,并在我定义的设置方法中初始化我的模拟对象:

@Before
public void setUp() throws Exception{
    MockitoAnnotations.initMocks(this);
}

Mockito版本:2.7.19

我希望能够测试API响应,所以我嘲笑了API服务,为改装回调定义了一个捕获器

1 个答案:

答案 0 :(得分:0)

你在这里尝试做什么有点奇怪。你正在测试一个类,但你嘲笑它。你应该测试真正的班级 - MyService。我假设您的服务看起来有点像:

public class MyService {
  private final Call<MyResponse> call;

  public MyService(Call<MyResponse> call) {
    this.call = call;
  }

  public void doSomeAction() {
    call.enqueue(...);
  }
}

理想情况下,你应该有类似的东西:

@RunWith(AndroidJUnit4.class)
public class SampleTest {

  private MyService mService;

  @Captor
  private ArgumentCaptor<Callback<MyResponse>> callbackArgumentCaptor;

  @Mock
  private Call<MyResponse> mockCall;

  @Rule
  public MockitoRule mockitoRule = MockitoJUnit.rule();

  @Before
  public void setUp() throws Exception{
   MockitoAnnotations.initMocks(this);

   mService = new MyService(mockCall);
  }

  @Test
  public void testDoAction() throws NullInsteadOfMockException {
    mService.doSomeAction();

    verify(mockCall).enqueue(callbackArgumentCaptor.capture());
   }
}

因此,我们的想法是模拟您进行单元测试的类的所有依赖关系,并以某种方式将它们传递给类。在这里,我将它们注入构造函数中。我不知道你是否属于这种情况,但是制定者或领域也是如此。

然后测试只是调用服务类中的real方法,如果这个方法假设要将调用入队,那么验证应该通过。

它在您的情况下不起作用的原因是因为您正在嘲笑该服务,所以当您致电mService.doSomeAction()时,这并不会调用您的实施,我认为应该致电{\ n} {1}}。这就是验证失败的原因。换句话说,永远不会在调用对象上调用enqueue