2016-03-24 9 views
3

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.

+0

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

+0

@ 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:' –

Antwort

4

Ich würde nicht empfehlen, Android-Klassen in den Referenten zu verwenden. Damit können Sie Ihren Moderator als lokalen Einheitstest testen (klassischer Java Unit Test).

Wenn Sie weiterhin Android-Klassen in Ihrem Moderator verwenden möchten, injizieren Sie die Abhängigkeiten des Moderators nicht mit Dolch. Was ich tun würde, ist, sie einfach durch den Konstruktor des Moderators zu leiten.

Spotte alle Abhängigkeiten des Moderators und erstelle den Presenter, der getestet wird. Sie verspotten den Moderator, den Sie testen möchten. Tun Sie das nicht, erstellen Sie einfach eine neue LoginPresenterImpl und übergeben Sie alle Abhängigkeiten über den Konstruktor in der Methode setUp, um sie zu initialisieren.

Here Sie haben ein paar großartige Beispiele für Presenter-Tests einfach gemacht.