如何在演示者层上编写适当的Android单元测试

时间:2016-03-24 02:59:17

标签: android unit-testing mockito mvp

我假设在使用模型 - 视图 - 演示者(MVP)模式时编写单元测试会更容易,但我不确定如何开始甚至开始。我添加了依赖项以开始使用RoboelectricMockito编写单元测试来模拟我的演示者中使用的所有依赖项。

作为参考,以下是我的登录演示者的示例:

public class LoginPresenterImpl implements ILoginPresenter {

@Inject
Bus bus;

@Inject
ISharedPreferencesRepository mSharedPreferencesRepository;

private final String LOG_TAG = "LOGIN_PRESENTER";
private ILoginView loginView;
private LoginInteractorImpl loginInteractor;
private long mLastClickTime = 0;

public LoginPresenterImpl() {
    MyApplication.getObjectGraph().inject(this);
    this.loginInteractor = new LoginInteractorImpl();
}

@Override
public void setLoginView(ILoginView loginView) {
    this.loginView = loginView;

    if(mSharedPreferencesRepository.isLoggedIn()) {
        Log.i(LOG_TAG, "User logged in already");
        this.loginView.navigateToHome();
    }
}

@Override
public void validateCredentials(String username, String password) {
    if(SystemClock.elapsedRealtime() - mLastClickTime < 1000)
        return;
    mLastClickTime = SystemClock.elapsedRealtime();

    if(username.equals("") || username == null) {
        loginView.setUsernameError();
        return;
    } else if(password.equals("") || password == null){
        loginView.setPasswordError();
        return;
    }

    loginView.showProgress();
    loginInteractor.login(username, password, this);
}

@Override
public void onUsernameError() {
    loginView.setUsernameError();
    loginView.hideProgress();
}

@Override
public void onPasswordError() {
    loginView.setPasswordError();
    loginView.hideProgress();
}

@Subscribe
@Override
public void onSuccess(LoginEvent event) {
    if (event.getIsSuccess()) {
        mSharedPreferencesRepository.setLogin(true);
        mSharedPreferencesRepository.setFirstTime(true);
        mSharedPreferencesRepository.setUserId(event.getUserId());

        loginView.navigateToHome();
        loginView.hideProgress();
    }
}

现在进行我的单元测试(尝试):

首先,如果我错了,请纠正我,但为了开始编写我的测试用例,我需要模拟一些对象: BusISharedPreferencesRepositoryILoginViewLoginInteractorImpl

我最终得到了类似的东西:

@RunWith(MockitoJUnitRunner.class)
public class LoginPresenterImplTest {

    @Mock
    private ILoginView view;

    @Mock
    private LoginInteractorImpl interactor;

    @Mock
    private LoginPresenterImpl presenter;

    @Before
    public void setUp(){

    }


    @Test
    public void shouldShowErrorMessageWhenUsernameIsEmpty() throws Exception {
        when(view.getUsername()).thenReturn("");
        when(view.getPassword()).thenReturn("test");
        presenter.validateCredentials(view.getUsername(), view.getPassword());
    }
}

我在接下来的步骤中有点失落。我正在尝试通过添加loiginView.setOnUsernameError()来验证在此方案中是否会调用方法verify(view, times(1)).setUsernameError();,但这无法通过我的测试。

1 个答案:

答案 0 :(得分:4)

我不建议在演示者中使用Android类。这将允许您将演示者测试为本地单元测试(经典的Java单元测试)。

如果您仍想在演示者中使用Android类,请不要使用dagger对presenter依赖项进行属性注入。我要做的就是将它们传递给演示者的构造函数。

然后,模拟所有演示者的依赖关系并创建将要测试的Presenter。您正在嘲笑要测试的演示者。不要这样做,只需创建一个新的LoginPresenterImpl并通过setUp方法中的构造函数将其所有依赖项传递给它来初始化它。

Here你有几个简单的演示者测试的例子。