2016-01-12 3 views
14

En utilisant Retrofit 1 nous avons utilisé pour les services Web simulés et simulent la latence du réseau comme suit:Comment se moquer des services avec Retrofit 2.0 et la nouvelle classe MockRetrofit?

MockRestAdapter mockRestAdapter = MockRestAdapter.from(restAdapter); 
return mockRestAdapter.create(MyService.class, new MyServiceMock()); 

MyService est le service d'interface (réponses de retour comme Rx Observables) et MyServiceMock est une classe qui implémente cette interface.

Dans Retrofit 2.0.0-beta3, il existe un tout nouveau système de simulation (voir: https://github.com/square/retrofit/pull/1343) qui n'est pas encore documenté. Lorsque vous essayez de de quelque chose de semblable, je reçois:

MockRetrofit mockRetrofit = new MockRetrofit.Builder(retrofit).build(); 
BehaviorDelegate<AuthService> delegate = mockRetrofit.create(MyService.class); 

Comment puis-je transférer les appels vers MyServiceMock?

+0

En passant, vous pouvez utiliser MockWebServer et MockResponse pour simuler moqueuse des services Web ainsi. –

+1

Je pense que vous pourriez bénéficier de l'utilisation de Mockery. Jetez un oeil;) https://github.com/VictorAlbertos/Mockery –

Répondre

15

On suppose la définition d'interface est comme ci-dessous:

public interface MyService { 
    @GET("/name") 
    rx.Observable<String> name(); 
} 

Les appels seront transmis à l'aide MyServiceMockBehaviorDelegate. Le BehaviorDelegate applique NetworkBehavior aux réponses créées par le simulacre. Notez que l'implémentation fictive ci-dessous prend le BehaviorDelegate en tant qu'argument de constructeur et l'utilise pour renvoyer la réponse.

public class MyServiceMock implements MyService { 
    private final BehaviorDelegate<MyService> delegate; 

    public MyServiceMock(BehaviorDelegate<MyService> delegate) { 
     this.delegate = delegate; 
    } 

    public Observable<String> name() { 
     return delegate.returningResponse("test").name(); 
    } 
} 

Un échantillon d'un test utilisant le service maquette est comme indiqué ci-dessous:

public class MyServiceTest { 

    private final NetworkBehavior behavior = NetworkBehavior.create(); 
    private final rx.observers.TestSubscriber<String> testSubscriber = TestSubscriber.create(); 
    private MyService mockService; 

    @Before 
    public void setUp() throws Exception { 
     Retrofit retrofit = new Retrofit.Builder() 
       .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 
       .baseUrl("http://example.com").build(); 

     MockRetrofit mockRetrofit = new MockRetrofit.Builder(retrofit) 
       .networkBehavior(behavior).build(); 

     final BehaviorDelegate<MyService> delegate = mockRetrofit.create(MyService.class); 

     mockService = new MyServiceMock(delegate); 
    } 

    @Test 
    public void testSuccessResponse() throws Exception { 
     givenNetworkFailurePercentIs(0); 

     mockService.name().subscribe(testSubscriber); 

     testSubscriber.assertValue("test"); 
     testSubscriber.assertCompleted(); 
    } 

    @Test 
    public void testFailureResponse() throws Exception { 
     givenNetworkFailurePercentIs(100); 

     mockService.name().subscribe(testSubscriber); 

     testSubscriber.assertNoValues(); 
     testSubscriber.assertError(IOException.class); 
    } 

    private void givenNetworkFailurePercentIs(int failurePercent) { 
     behavior.setDelay(0, MILLISECONDS); 
     behavior.setVariancePercent(0); 
     behavior.setFailurePercent(failurePercent); 
    } 
} 
+1

Ok, donc si je comprends bien, je vais devoir réécrire tous mes simulacres pour ajouter le passe-partout suivant 'delegate.returning (myMockedValue) .myMethod();' . Je ne suis pas sûr que ce soit une amélioration par rapport à Retrofit 1. – clemp6r

+0

Y at-il une raison d'écrire jamais 'delegate.returning (Calls.response (quelque chose))' si vous pouvez appeler 'delegate.returningResponse (quelque chose))', qui fait la partie "Calls.response()" pour vous? – Singed

+1

@Singed - Vous avez raison. Il n'y a aucune raison d'écrire le formulaire long dans ce cas. 'returnResponse' peut être utilisé. Cependant, lorsque cela peut être utile, c'est quand vous voulez envoyer des réponses ratées de votre maquette. Exemple 'delegate.returning (Calls.failure (nouvelle IOException (" une erreur ")))'. –