2015-05-01 10 views
11

ja oddzielone modernizacyjny API wywołuje metody z kodem działalności i chcę zrobić test jednostki na tych metodach, jeden przykład: Interfejs:Android Test jednostki z modernizacją i Mockito

public interface LoginService { 
    @GET("/auth") 
    public void basicLogin(Callback<AuthObject> response); 
} 

i to jest metoda, która wykonuje wywołanie, w głównym działaniu otrzymuję obiekt przez magistralę zdarzeń.

public class AuthAPI { 
    private Bus bus; 
    LoginService loginService; 

    public AuthAPI(String username, String password) { 
     this.bus = BusProvider.getInstance().getBus(); 
     loginService = ServiceGenerator.createService(LoginService.class, 
       CommonUtils.BASE_URL, 
       username, 
       password); 
    } 

    public void Login() { 

     loginService.basicLogin(new Callback<AuthObject>() { 
      @Override 
      public void success(AuthObject authObject, Response response) { 
       bus.post(authObject); 
      } 

      @Override 
      public void failure(RetrofitError error) { 
       AuthObject authObject = new AuthObject(); 
       authObject.setError(true); 
       bus.post(authObject); 
      } 
     }); 
    } 

} 

A oto test

@RunWith(MockitoJUnitRunner.class) 
public class AuthCallTest extends TestCase { 

    AuthAPI authAPI; 

    @Mock 
    private LoginService mockApi; 

    @Captor 
    private ArgumentCaptor<Callback<AuthObject>> cb; 

    @Before 
    public void setUp() throws Exception { 
     authAPI = new AuthAPI("username", "password"); 
     MockitoAnnotations.initMocks(this); 
    } 

    @Test 
    public void testLogin() throws Exception { 

     Mockito.verify(mockApi).basicLogin((cb.capture())); 

     AuthObject authObject = new AuthObject(); 
     cb.getValue().success(authObject, null); 

     assertEquals(authObject.isError(), false); 
    } 
} 

kiedy uruchomić test mam ten błąd

Wanted but not invoked: 
mockApi.basicLogin(<Capturing argument>); 
-> at AuthCallTest.testLogin(AuthCallTest.java:42) 
Actually, there were zero interactions with this mock. 

Co zrobiłem źle, to doprowadza mnie do szału starałem się śledzić to przewodnik bez powodzenia: http://www.mdswanson.com/blog/2013/12/16/reliable-android-http-testing-with-retrofit-and-mockito.html

someon Pomóżcie mi :(

+0

Problem polega na tym, że śledzisz blog, który ma ponad dwa lata. Co więcej, autor nie aktualizował swojego kodu przez dwa lata i nie jest zainteresowany. –

Odpowiedz

21

Artykuł nie jest zbyt jasny, ponieważ pomija kroki instalacji. Przeglądając link do artykułu GitHub project, można zobaczyć pełny kod źródłowy wyjaśniający te brakujące kroki:

1) Próbki kodu są pobierane z klasy testowej testującej określoną aktywność. W ramach konfiguracji (tj. W @Before) zastępuje odniesienie do działania do implementacji interfejsu API GitHub w wersji próbnej. Następnie wywołuje aktywność obiektu onCreate().

2) Podczas onCreate(), działanie powoduje wywołanie nowoutworzonego API GitHub, przekazując obiekt Callback.

Te pierwsze dwa kroki wyjaśniają, dlaczego krok Mockito.verify(mockApi).repositories(Mockito.anyString(), cb.capture()); krok na początku każdego testu działa. Ponieważ test jest uruchamiany po @Before, funkcja mockApi rzeczywiście wywołała metodę .

Reszta kodu jest łatwiejsza do zrozumienia, gdy już jest na miejscu. Ponieważ został utworzony tylko mockApi, ale nie zmieniono rzeczywistego używanego Callback, treść działania zostanie zmieniona. Reszta kodu następnie sprawdza, czy te zmiany miały miejsce, albo sprawdzając ListView lub toasty.


Tak, aby odpowiedzieć na to pytanie, trzeba:

1) Na początku swojej metody badawczej, wymienić loginService Object AuthAPI jest z obiektem mockApi, a następnie zadzwonić AuthAPI.Login().

2) Użyj verify(), aby sprawdzić, czy funkcja została wywołana.

3) Utwórz próbkę AuthObject i przekaż ją do funkcji cb.getValue().success().

4) Uzyskaj numer AuthObject z numeru Bus i potwierdź, że jest to ten sam, który został wysłany do funkcji callback.success().

Ten test sprawi, że Twój AuthAPI.Login() prawidłowo wyśle ​​do Twojego telefonu BusAuthObject, który pobierze z Retrofitu.


(zdaję sobie sprawę, pytanie SO został napisany jakiś czas temu, ale jak natknąłem tego samego artykułu i miał ten sam nieporozumienia niedawna myślałem, że odpowiedź ta może być przydatna dla innych.)

+0

Dzięki za wskazanie. – rogerstone

+0

Wygląda na to, że chcesz testować swoje testy w kontekście aktywności Androida. Nie sądzę, że jest to najczystsze podejście do testowania interfejsów REST API - które powinny być testowane na JVM (junit). –

+1

@IgorGanapolsky Nie można bezpośrednio testować interfejsów REST API w aplikacji na Androida w JUnit, jeśli używasz dowolnej klasy odwołującej się do zestawu SDK systemu Android, ponieważ JUnit nie ładuje klas Android. Jednak to jest celem powyższego artykułu - jak używać Robolectric i Mockito do wykonywania lokalnych testów interfejsów API REST bez wykonywania rzeczywistych wywołań serwera, jednocześnie wciąż uzyskując dostęp do prawdziwych klas Android. –

1

Problem polega na tym, że w nieodpowiednim momencie wywołuje się verify: celem verify jest sprawdzenie, czy interakcje z mockApi były zgodne z oczekiwaniami. Tak normalnie można zobaczyć coś takiego:

authApi.login(); 
Mockito.verify(mockApi).basicLogin((cb.capture())); 

to także, co jest komunikat o błędzie z informacją: verify oczekiwanego basicLogin być nazywany ale tak nie było.

Przeczytałam ten artykuł i poczułam, że czegoś mi brakuje. Właściwie nie zbieram argumentów. Więc nic na to nie poradzę :)