【问题标题】:How to mock services with Retrofit 2.0 and the new MockRetrofit class?如何使用 Retrofit 2.0 和新的 MockRetrofit 类模拟服务?
【发布时间】:2016-04-16 21:23:19
【问题描述】:

我们使用 Retrofit 1 来模拟 Web 服务并模拟网络延迟,如下所示:

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

MyService 是服务接口(将响应作为 Rx Observables 返回),MyServiceMock 是实现此接口的类。

在 Retrofit 2.0.0-beta3 中,有一个全新的模拟系统(请参阅:https://github.com/square/retrofit/pull/1343)尚未记录。 当尝试做类似的事情时,我得到:

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

如何将呼叫转接到MyServiceMock

【问题讨论】:

  • 顺便说一句,您也可以使用 MockWebServer 和 MockResponse 来模拟模拟 Web 服务。
  • 我认为你可以从使用 Mockery 中受益。看看 ;) github.com/VictorAlbertos/Mockery

标签: java rx-java retrofit2


【解决方案1】:

假设接口定义如下:

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

呼叫将使用BehaviorDelegate 转接到MyServiceMockBehaviorDelegateNetworkBehavior 应用于模拟创建的响应。请注意,下面的模拟实现将BehaviorDelegate 作为构造函数参数并使用它来返回响应。

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();
    }
}

使用模拟服务的测试示例如下所示:

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);
    }
}

【讨论】:

  • 好的,如果我明白了,我将不得不重写我所有的模拟来添加以下样板文件delegate.returning(myMockedValue).myMethod();。我不确定这与 Retrofit 1 相比是否有所改进。
  • 如果你可以打电话给delegate.returningResponse(something)),你有理由写delegate.returning(Calls.response(something))吗?“Calls.response()”部分适合你吗?
  • @Singed - 你是对的。在这种情况下,没有理由编写长格式。可以使用returningResponse。然而,当你想从你的模拟中发送失败的响应时,这可能很有用。示例delegate.returning(Calls.failure(new IOException("some error"))).
  • 我相信 BehaviorDelegate 使用反射作为其接口。是不是有点绕?我想知道是否有更直接/更简单的方法来测试 Web 服务。
  • @LanceContreras - 我相信您是在询问 name() 上的 subscribe() 方法调用。由于 name() 是 RxJava Observable,我在其上调用 subscribe() 方法。
猜你喜欢
  • 2014-09-17
  • 1970-01-01
  • 1970-01-01
  • 2019-03-18
  • 1970-01-01
  • 1970-01-01
  • 2017-11-14
  • 2017-02-14
  • 2017-01-20
相关资源
最近更新 更多