Android Unit Test with Retrofit and Mockito



我将改造 api 调用方法与活动代码分开,我想对这些方法进行单元测试,例如: 界面:

public interface LoginService {
@GET("/auth")
public void basicLogin(Callback<AuthObject> response);
}

这是执行调用的方法,在主活动中,我通过事件总线获取对象。

public class AuthAPI {
private Bus bus;
LoginService loginService;
public AuthAPI(String username, String password) {
this.bus = BusProvider.getInstance().getBus();
loginService = ServiceGenerator.createService(LoginService.class,
CommonUtils.BASE_URL,
username,
password);
}
public void Login() {
loginService.basicLogin(new Callback<AuthObject>() {
@Override
public void success(AuthObject authObject, Response response) {
bus.post(authObject);
}
@Override
public void failure(RetrofitError error) {
AuthObject authObject = new AuthObject();
authObject.setError(true);
bus.post(authObject);
}
});
}
}

这里是测试

@RunWith(MockitoJUnitRunner.class)
public class AuthCallTest extends TestCase {
AuthAPI authAPI;
@Mock
private LoginService mockApi;
@Captor
private ArgumentCaptor<Callback<AuthObject>> cb;
@Before
public void setUp() throws Exception {
authAPI = new AuthAPI("username", "password");
MockitoAnnotations.initMocks(this);
}
@Test
public void testLogin() throws Exception {
Mockito.verify(mockApi).basicLogin((cb.capture()));
AuthObject authObject = new AuthObject();
cb.getValue().success(authObject, null);
assertEquals(authObject.isError(), false);
}
}

当我启动测试时,我遇到此错误

Wanted but not invoked:
mockApi.basicLogin(<Capturing argument>);
-> at AuthCallTest.testLogin(AuthCallTest.java:42)
Actually, there were zero interactions with this mock.

我做错了什么,这让我发疯 我试图遵循本指南但没有成功: http://www.mdswanson.com/blog/2013/12/16/reliable-android-http-testing-with-retrofit-and-mockito.html

有人帮我:(

这篇文章不是很清楚,因为它错过了设置步骤。通过访问文章中链接的 GitHub 项目,您可以看到完整的源代码,其中解释了这些缺失的步骤:

1) 代码示例是从测试特定活动的测试类中提取的。作为设置的一部分(即在@Before中),它将活动对 GitHub API 实现的引用替换为模拟实现。然后,它调用活动的onCreate()

2)在onCreate()期间,活动调用现在被替换的GitHub API,传入其Callback对象。

前两个步骤解释了为什么每个测试开始时的Mockito.verify(mockApi).repositories(Mockito.anyString(), cb.capture());步骤有效。由于测试是在@Before之后运行的,mockApi 确实调用了它的repositories()方法。

一旦到位,其余代码就更容易理解了。由于他只创建了一个mockApi,但没有更改实际使用的Callback,因此活动的内容会更改。然后,代码的其余部分通过检查 ListView 或 Toast 来验证这些更改是否已发生。


因此,要回答您的问题,您需要:

1) 在测试方法开始时,将 AuthAPI 的 loginService 对象替换为 mockApi 对象,然后调用AuthAPI.Login()

2) 使用verify(),就像你已经一样检查函数是否已被调用。

3) 创建一个示例AuthObject并将其传递给cb.getValue().success()函数。

4) 从您的Bus获取AuthObject,并断言它与您发送给callback.success()函数的相同。

这将测试您的AuthAPI.Login()是否正确地发送到您的Bus它将从 Retrofit 检索AuthObject


(我意识到SO问题是前段时间写的,但是当我最近遇到同一篇文章并且有同样的困惑时,我认为这个答案可能对其他人有用。

问题是你在错误的时刻调用verifyverify的目的是验证与 mockAPI 的交互是否符合您的预期。所以通常你会看到类似的东西:

authApi.login();
Mockito.verify(mockApi).basicLogin((cb.capture()));

这也是错误消息告诉您的:verify期望调用basicLogin,但事实并非如此。

我也读过那篇文章,觉得缺少一些东西。我实际上还没有取消争论捕获。所以帮不了你那个:)

相关内容

  • 没有找到相关文章