我将改造 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问题是前段时间写的,但是当我最近遇到同一篇文章并且有同样的困惑时,我认为这个答案可能对其他人有用。
问题是你在错误的时刻调用verify
:verify
的目的是验证与 mockAPI 的交互是否符合您的预期。所以通常你会看到类似的东西:
authApi.login();
Mockito.verify(mockApi).basicLogin((cb.capture()));
这也是错误消息告诉您的:verify
期望调用basicLogin
,但事实并非如此。
我也读过那篇文章,觉得缺少一些东西。我实际上还没有取消争论捕获。所以帮不了你那个:)