我有以下课程,我正试图弄清楚如何编写单元测试:
@EBean
public class LoginInteractorImpl implements LoginInteractor {
private final static String LOGIN_INTERACTOR_THREAD_ID = "LOGIN_INTERACTOR_WORKER";
private UserRepo mUserRepository;
private Call<ResponseBody> mCall;
@Override
@Background(id = LOGIN_INTERACTOR_THREAD_ID)
public void login(final String username, final String password, final OnLoginFinishedListener listener) {
mUserRepository = RetrofitHelper.createClient(UserRepo.class);
mCall = mUserRepository.doLogin(Credentials.basic(username, password));
mCall.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
final int code = response.code();
if (code == 200) {
listener.onSuccess(response.headers().get(""));
} else if (code == 401) {
listener.invalidCredentialsFailure();
} else if (code >= 400 && code < 500) {
listener.invalidCredentialsFailure();
} else if (code >= 500 && code < 600) {
listener.noServerResponseFailure();
} else {
APIError error = ErrorUtils.parseError(response);
listener.onError("Unexpected response: code:"
+ error.getStatusCode()
+ "message: " + error.getMessage());
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
if (t instanceof IOException) {
listener.noNetworkFailure();
} else if(call.isCanceled()) {
Log.e(TAG, "request was aborted");
} else {
listener.onError(t.getMessage());
}
}
});
}
@Override
public void cancel() {
mCall.cancel();
BackgroundExecutor.cancelAll(LOGIN_INTERACTOR_THREAD_ID, true);
}
}
使用Retrofit我正在调用我的webservice进行身份验证,webservice应该返回一个Authtoken供以后使用。我只是无法掌握如何测试这个。我尝试使用Mockito创建解决方案,但我无法弄清楚如何测试登录方法的逻辑。是否有任何关于Mockito / Retrofit的专家可以指导我更接近工作解决方案?
答案 0 :(得分:3)
在尝试任何单元测试之前,我会重构一些事情:
1)从enqueue
方法中创建的匿名类创建一个显式的Callback类。让我们称之为LoginCallback
:
public class LoginCallback implements Callback{
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
final int code = response.code();
if (code == 200) {
...
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
if (t instanceof IOException) {
listener.noNetworkFailure();
...
}
}
现在,您对这两种方法逻辑执行隔离单元测试。
2)将静态方法调用移动到包级别方法。你最终会得到这样的东西:
public class LoginInteractorImpl implements LoginInteractor {
public void login(final String username, final String password, final OnLoginFinishedListener listener) {
mUserRepository = createClient();
mCall = mUserRepository.doLogin(getCredentials(username,password));
mCall.enqueue(new LoginCallback());
}
UserRepo createClient(){
RetrofitHelper.createClient(UserRepo.class)
}
Credentials getCredentials(String username, String password){
return Credentials.basic(username, password)
}
}
3)单元测试login
方法
@RunWith(JunitMockitoRunner.class)
public class TestClass{
@Spy
private LoginInteractorImpl loginInterceptor= new LoginInteractorImpl();
@Mock
private UserRepo mUserRepositoryMock;
@Mock
private Call<ResponseBody> mCallMock;
@Mock
private Credentials credentialsMock;
public void shouldEnqueueWhenLogin(){
// Arrange
String username = "name";
String password = "pass";
Mockito.doReturn(mUserRepositoryMock).when(loginInterceptor).createClient();
Mockito.doReturn(credentialsMock).when(loginInterceptor).when(getCredentials(username, password));
Mockito.doReturn(mCallMock).when(mUserRepositoryMock).doLogin(credentialsMock);
// Act
loginInterceptor.login(username, password);
// Assert that proper callback has been passed to enqueue
verify(mCallMock).enqueue(Mockito.any(LoginCallback.class));
}
}