Ich war unter der Annahme, dass Schreiben von Unit-Tests wäre viel einfacher bei der Verwendung der Model-View-Presenter (MVP) Muster, aber ich bin mir nicht sicher, wie es geht vorwärts mit gleichmäßigem Anfang. Ich habe Abhängigkeiten hinzugefügt, um Unit-Tests mit Roboelectric
und Mockito
zu schreiben, um alle Abhängigkeiten zu verspotten, die in meinem Presenter verwendet werden.Wie schreibe ich einen richtigen Android-Unit-Test auf der Presenter-Ebene
Für einige Referenz, hier ist ein Beispiel für meinen Moderator für die Anmeldung:
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();
}
}
Jetzt auf meinen Unit-Test (Versuch):
Zuerst korrigieren Sie mich, wenn ich falsch liege, aber in Um mit dem Schreiben meiner Testfälle zu beginnen, muss ich einige Objekte verspotten: Bus
, ISharedPreferencesRepository
, ILoginView
, LoginInteractorImpl
.
endete ich mit so etwas wie dies oben:
@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());
}
}
Ich bin ein bisschen in den nächsten Schritten verloren zu nehmen. Ich versuche zu überprüfen, dass die Methode loiginView.setOnUsernameError()
in diesem Szenario aufgerufen wird, indem verify(view, times(1)).setUsernameError();
hinzufügt, aber das schlägt meinen Test fehl.
Sind Sie sicher, dass es tatsächlich 'validateCredentials' aufruft? Es sieht so aus, als wäre der Moderator ein Spott. Versuchen Sie, 'when (presenter.validateCredentials (any(), any()). ThenCallRealMethod();' vor dem eigentlichen Aufruf. – ncphillips
@ ncphillips Da meine 'validateCredentials()' void zurückgibt, musste ich es so machen : 'doNothing(). Wenn (Moderator) .validateCredentials (" Benutzername "," Passwort "));' Aber das warf mich 'org.mockito.exceptions.misusing.UnfinishedStubbingException:' –