2012-07-06 22 views
5

mam tej klasy do testów usługi zdalnej:Android usługa uruchomiona przez nie testów JUnit

public class CoreServiceBasicTest extends ServiceTestCase<CoreService> implements ServiceConnection { 

    /** Tag for logging */ 
    private final static String TAG = CoreServiceBasicTest.class.getName(); 

    /** Receive incoming messages */ 
    private final Messenger inMessenger = new Messenger(new IncomingHandler()); 

    /** Communicate with the service */ 
    private Messenger outMessenger = null; 

    /** Handler of incoming messages from service */ 
    private static class IncomingHandler extends Handler { 

     @Override 
     public void handleMessage(Message msg) { 
      Log.d(TAG, "Incoming message"); 
     } 
    } 

    /** Constructor for service test */ 
    public CoreServiceBasicTest() { 
     super(CoreService.class); 
    } 

    /** Start the service */ 
    @Override 
    public void setUp() { 

     // Mandatory 
     try { 
      super.setUp(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 

     // Start the service 
     Intent service = new Intent(); 
     service.setClass(this.getContext(), CoreService.class); 
     startService(service); 
     Log.d(TAG, "Service started"); 
    } 

    public void onServiceConnected(ComponentName className, IBinder service) { 
     outMessenger = new Messenger(service); 
     Log.d(TAG, "Service attached"); 
    } 

    public void onServiceDisconnected(ComponentName className) { 
     // TODO Auto-generated method stub 

    } 

    @SmallTest 
    public void testBindService() { 
     // Bind to the service 
     Intent service = new Intent(); 
     service.setClass(getContext(), CoreService.class); 
     boolean isBound = getContext().bindService(service, this, Context.BIND_AUTO_CREATE); 
     assertTrue(isBound); 
    } 
} 

Problem polega na tym, że StartService (usługi) w metodzie setup() nie poprawnie uruchomić usługę. To co pokazuje AVD:

enter image description here

Jak widać, proces jest uruchomiony, ale obsługa nie jest. Następnie na testBindService(), assertTrue(isBound) kończy się niepowodzeniem.

nie stanie, jeśli uruchomić usługę z działalności:

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    // Start the Core service 
    Intent service = new Intent(); 
    service.setClass(this, CoreService.class); 

    if (startService(service) == null) { 
     Toast.makeText(this, "Error starting service!", Toast.LENGTH_LONG).show(); 
     Log.e(TAG, "Error starting service"); 
    } else { 
     Toast.makeText(this, "Service started sucessfully", Toast.LENGTH_LONG).show(); 
    } 

    // Die 
    finish(); 
} 

Tutaj usługa jest uruchomiona poprawnie, tak jak pokazano poniżej.

enter image description here

Jak mogę zacząć i wiążą się ze zdalną obsługę, która używa Messenger komunikowania się z działalności z projektem Android test?

+0

Najpierw wykonaj te kontrole, aby upewnić się, że jest to podstawowy problem, a nie coś, co jest składniowe po raz pierwszy Upewnij się, że twój manifest ma ten numer: ' i jest zagnieżdżony pomiędzy tagiem aplikacji, tak jak" ' Upewnij się również, że wszystkie zależności projektu są poprawnie odwzorowane Sprawdź również, czy twój coreservice.java jest w tym samym pakiecie lub inny pakiet jako działanie - upewnij się, że nazwy pakietów są poprawne w manifeście. – Slartibartfast

+0

Jak już powiedziałem: * "Tak się nie stanie, jeśli uruchomię usługę z działania" *, więc oczywiste jest, że Manifest jest poprawny. Jak widać, nie ma błędu "Nie znaleziono usługi", ale proces jest uruchamiany, ale nie ma dołączonej usługi? To jest coś, co wydaje mi się dziwne. – m0skit0

Odpowiedz

11

Cały punkt Android Test Project (test.apk) polega na instrumentizacji Projektu Aplikacji (app.apk) i testowaniu jednostkowych komponentów Androida (Aktywność, Usługa i itp.) Związanych z Projektem aplikacji, w innym słowo, testowanie jednostkowe Activity and Service, które jest tworzone i modyfikowane wewnątrz app.apk.

Nie należy częściowo pisać implementacji usługi MessengerService (Messenger, IncomingHandler itd.) W ramach implementacji ServiceTestCase w ramach projektu testowego. Implementacja MessengerService musi zostać napisana tylko raz w pliku CoreService.java projektu aplikacji.

ServiceConnection służy do komunikacji między działaniem a usługą, ponieważ korzystamy z ServiceTestCase tutaj (oznacza usługę testu jednostkowego, komunikacja z innymi komponentami jest poza zakresem, dlatego nie jest brany pod uwagę), nie potrzebujemy połączenia ServiceConnection realizacja. Jedyną rzeczą ServiceConnection nie jest zainicjować ciężki przedmiot Messenger, dzięki czemu możemy użyć później, gdy usługa jest poprawnie utworzony:

public void onServiceConnected(ComponentName className, IBinder service) { 
    // This is what we want, we will call this manually in our TestCase, after calling 
    // ServiceTestCase.bindService() and return the IBinder, check out code sample below. 
    mService = new Messenger(service); 
} 

Należy również pamiętać, że nie trzeba zadzwonić ServiceTestCase.startService() w tym przypadku, jako ServiceTestCase.bindService() poprawnie uruchomi usługę (jeśli jeszcze nie jest uruchomiona) i zwróci obiekt IBinder, którego musimy użyć, aby później zainicjować obiekt Messenger.

Say jeśli IncomingHandler.handleMessage() impelementation w CoreService.java wyglądać następująco:

... ... 

switch (msg.what) { 
    case MSG_SAY_HELLO: 
    msgReceived = true; 
    break; 

... ... 

Aby przetestować funkcje wysłać wiadomość w ServiceTestCase:

... ... 

IBinder messengerBinder = null; 

@Override 
public void setUp() throws Exception { 
    super.setUp(); 
    // Bind the service and get a IBinder: 
    messengerBinder = bindService(new Intent(this.getContext(), CoreService.class)); 
    //log service starting 
    Log.d(TAG, "Service started and bound"); 
} 

public void testSendMessage() { 
    // Use IBinder create your Messenger, exactly what we did in ServiceConnection callback method: 
    Messenger messenger = new Messenger(messengerBinder); 
    Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0); 
    messenger.send(msg); 
    // Do some assert stuff here 
    ... ... 
} 

... ... 

Jeśli chcesz przetestować komunikację między Aktywność i serwis, a następnie ServiceTestCase nie jest odpowiedni w tym przypadku. Rozważ skorzystanie z testu ActivityInstrumentationTestCase2 i sprawdź rzeczywistą aktywność (która jest powiązana z CoreService, co daje możliwość pośredniego przetestowania Twoich funkcji serwisowych.)

+0

Tak, dokładnie to chciałem zrobić: przetestuj wysyłanie wiadomości do usługi, a nie komunikację usługową o aplikacji <->. Dziękuję Ci! – m0skit0

+0

@ m0skit0, cieszę się, że to pomaga :) – yorkw

7

Tylko patrząc na documentation for ServiceTestCase mówi, że ramy testu opóźnienia, począwszy od służby aż do jednej z metod badań zwraca ServiceTestCase.startService() lub ServiceTestCase.bindService().

Patrząc na swój kod, należy zadzwonić pod numer ServiceTestCase.startService() w swojej metodzie setUp(), nie w metodzie testowej. To jeszcze nie uruchamia usługi. Czeka na jedną z twoich metod testowania, aby zadzwonić pod numer ServiceTestCase.startService() lub.

Twoja metoda testowa testBindService() nie wywołuje ServiceTestCase.bindService(), zamiast tego wywołuje Context.bindService() i kończy się niepowodzeniem. Struktura testowa wciąż czeka, dlatego usługa nie została uruchomiona.

Zobacz jeszcze raz dyskusję na temat wsparcia cyklu życia w powiązanych dokumentach programisty.

+0

Problem polega na tym, że nie mogę wywołać metody 'ServiceTestCase.bindService()', która jest dla mnie bezużyteczna, ponieważ nie wymaga połączenia "ServiceConnection". – m0skit0

+1

Struktura testowa zajmuje się wszystkimi elementami połączenia. Zarządza usługą ServiceConnection. Kiedy wywołujesz 'ServiceTestCase.bindService()' zwraca IBinder, który i tak byś użył ServiceConnection. W każdym razie, jeśli nie możesz użyć tego szkieletu testowego do testowania, ponieważ nie zapewnia on odpowiednich możliwości lub interfejsu, potrzebujesz tylko napisać własną wiązkę testową bez korzystania z tej platformy. –

Powiązane problemy