使用Mockito测试MVP Android应用程序

使用Mockito测试MVP Android应用程序,android,mockito,retrofit,mvp,Android,Mockito,Retrofit,Mvp,我试图在一个基本的Android应用程序上做一些单元测试。它只是使用“我的应用程序具有MVP模式”的改型登录到一些WS 我在做什么 调用presenter层这将调用interactor,在这里我将调用我的服务 @Override public void doLogin(String user, String pwd, final LoginListener loginListener) { try { final LoginRequest

我试图在一个基本的Android应用程序上做一些单元测试。它只是使用“我的应用程序具有MVP模式”的改型登录到一些WS

我在做什么

调用presenter层这将调用interactor,在这里我将调用我的服务

    @Override
    public void doLogin(String user, String pwd, final LoginListener loginListener) {

        try {
            final LoginRequest request = new LoginRequest();
            request.setEmpleado(user);
            request.setPwd(pwd);

            Callback<LoginResponse> callback = new Callback<LoginResponse>() {
                @Override
                public void onResponse(Call<LoginResponse> call, Response<LoginResponse> response) {
                    if(response != null && response.isSuccessful() && response.body() != null) {
                        if("00".equals(response.body().getCodigo())) {
                            loginListener.authOK();
                        } else {
                            loginListener.showError();
                        }
                    } else {
                        loginListener.showError();
                    }
                }

                @Override
                public void onFailure(Call<LoginResponse> call, Throwable t) {
"+t.getMessage()+" "+t.getCause());
                    if(t instanceof SocketTimeoutException) {
                        loginListener.showError();
                    } else {
                        loginListener.showError();
                    }
                }
            };

            WSLogin wsLogin = RetrofitClient.getInstance().getRetrofit().create(WSLogin.class);
            wsLogin.autenticar(request).enqueue(callback);

        } catch (Exception e) {
            loginListener.showError();
            e.printStackTrace();
        }
@覆盖
public void doLogin(字符串用户、字符串pwd、最终登录列表器登录列表器){
试一试{
最终登录请求=新登录请求();
请求.setEmpleado(用户);
请求。setPwd(pwd);
Callback Callback=new Callback(){
@凌驾
公共void onResponse(调用、响应){
if(response!=null&&response.issucessful()&&response.body()!=null){
如果(“00”.equals(response.body().getCodigo())){
loginListener.authOK();
}否则{
loginListener.bathror();
}
}否则{
loginListener.bathror();
}
}
@凌驾
失败时公共无效(调用调用,可丢弃的t){
“+t.getMessage()+”+t.getCause());
if(SocketTimeoutException的t实例){
loginListener.bathror();
}否则{
loginListener.bathror();
}
}
};
WSLogin WSLogin=RefughtClient.getInstance().GetRefught().create(WSLogin.class);
wsLogin.autenticar(请求).enqueue(回调);
}捕获(例外e){
loginListener.bathror();
e、 printStackTrace();
}
我的服务已经打过了,但我从来没有回过电话

试验

package com.arleckk.loginmvpci.login;
导入com.arleckk.loginmvpci.login.presenter.LoginListener;
导入com.arleckk.loginmvpci.login.presenter.LoginPresenter;
导入com.arleckk.loginmvpci.login.presenter.loginpresentrempl;
导入com.arleckk.loginmvpci.login.view.LoginView;
导入com.arleckk.loginmvpci.model.LoginResponse;
导入com.arleckk.loginmvpci.network.WSLogin;
导入org.junit.Before;
导入org.junit.Test;
导入org.junit.runner.RunWith;
导入org.mockito.Mock;
导入org.mockito.mockito;
导入org.mockito.MockitoAnnotations;
导入org.mockito.junit.MockitoJUnitRunner;
导入org.powermock.core.classloader.annotations.PowerMockIgnore;
导入org.powermock.modules.junit4.PowerMockRunner;
导入java.io.IOException;
2.电话;;
2.回应;;
导入静态org.junit.Assert.assertEquals;
@RunWith(PowerMockRunner.class)
@PowerMockIgnore(“javax.net.ssl.*”)
公共类登录测试{
@模拟私人LoginView LoginView;
@模拟私人登录Presenter登录Presenter;
@模拟私有登录列表器登录列表器;
@模拟私人呼叫登录ResponseCall;
响应日志响应响应;
@以前
公共作废设置(){
initMocks(this);
loginPresenter=新的LoginPresentImpl(loginView);
}
@试验
public void testOK()引发IOException{
loginPresenter.doLogin(“测试”、“测试1234”);
}
}
另一个问题是:我真的在做单元测试吗?我的意思是单元测试只测试代码的“单元”


我需要一个LoginResponse对象,然后比较它是否等于“00”“它是成功的

不,你不是。有几个原因。首先,这里没有测试。你没有一个断言。不管发生什么情况,你的代码都会说通过。所以这不是一个测试。测试是说使用工作登录名调用doLogin,并确保loginListener.authOK()然后,另一个测试使用了错误的密码,并检查是否调用了淋浴ROR。如果不这样做,您所拥有的一切就是浪费时间

第二,对于单元测试来说,这是一个可怕的范围。对于单元测试,你应该检查最小的代码单元是否工作。在这里,你要检查你的整个网络堆栈和你的服务器是否都工作。这太过分了。而单元测试决不应该依赖外部服务器工作,这只会导致一个不稳定的测试——有些这样的东西应该放在集成套件中


您的代码目前没有针对测试进行优化。如果是,您就不会通过代码中的单例创建改装客户端。您应该将其传递到doLogin。这样,您可以在可能返回虚假响应的测试中传递模拟,然后测试您的代码是否能够正确识别虚假成功和失败响应首先,删除服务器依赖项还需要测试所有功能。

不,你没有。有几个原因。首先,你在这里没有测试。你没有一个断言。不管发生什么情况,你的代码都会说通过。所以这不是一个测试。测试是说使用工作登录名调用doLogin,并确保loginListener、 调用authOK()。然后,另一个使用错误密码的测试将检查是否调用了淋浴ROR。如果不这样做,您将浪费时间

第二,对于单元测试来说,这是一个可怕的范围。对于单元测试,你应该检查最小的代码单元是否工作。在这里,你要检查你的整个网络堆栈和你的服务器是否都工作。这太过分了。而单元测试决不应该依赖外部服务器工作,这只会导致一个不稳定的测试——有些这样的东西应该放在集成套件中

您的代码目前没有针对测试进行优化。如果是,您就不会通过代码中的单例创建改装客户端。您应该将其传递到doLogin。这样,您可以在可能返回虚假响应的测试中传递模拟,然后测试您的代码是否能够正确识别虚假成功和失败响应首先,删除服务器依赖项,然后测试所有
package com.arleckk.loginmvpci.login;


import com.arleckk.loginmvpci.login.presenter.LoginListener;
import com.arleckk.loginmvpci.login.presenter.LoginPresenter;
import com.arleckk.loginmvpci.login.presenter.LoginPresenterImpl;
import com.arleckk.loginmvpci.login.view.LoginView;
import com.arleckk.loginmvpci.model.LoginResponse;
import com.arleckk.loginmvpci.network.WSLogin;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnitRunner;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.modules.junit4.PowerMockRunner;

import java.io.IOException;

import retrofit2.Call;
import retrofit2.Response;

import static org.junit.Assert.assertEquals;

@RunWith(PowerMockRunner.class)
@PowerMockIgnore("javax.net.ssl.*")
public class LoginTest {

    @Mock private LoginView loginView;
    @Mock private LoginPresenter loginPresenter;
    @Mock private LoginListener loginListener;
    @Mock private Call<LoginResponse> loginResponseCall;
    Response<LoginResponse> loginResponseResponse;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
        loginPresenter = new LoginPresenterImpl(loginView);
    }

    @Test
    public void testOK() throws IOException {
        loginPresenter.doLogin("TEST", "TEST1234");
    }


}