我正在寻找一种在安卓测试中模拟 api 响应的方法。
我已经阅读了机器人电动可以用于此目的,但我非常感谢对此的任何建议。
在网上浏览了一会儿后,我发现MockWebServer就是我想要的。
用于测试 HTTP 客户端的可编写脚本的 Web 服务器。通过此库,可以轻松测试应用在进行 HTTP 和 HTTPS 调用时是否执行正确的操作。它允许您指定要返回的响应,然后验证请求是否按预期发出。
要进行设置,只需将以下内容添加到您的build.gradle文件中。
androidTestCompile 'com.google.mockwebserver:mockwebserver:20130706'
这是从他们的GitHub页面中获取的一个简单的示例。
public void test() throws Exception {
// Create a MockWebServer. These are lean enough that you can create a new
// instance for every unit test.
MockWebServer server = new MockWebServer();
// Schedule some responses.
server.enqueue(new MockResponse().setBody("hello, world!"));
// Start the server.
server.play();
// Ask the server for its URL. You'll need this to make HTTP requests.
URL baseUrl = server.getUrl("/v1/chat/");
// Exercise your application code, which should make those HTTP requests.
// Responses are returned in the same order that they are enqueued.
Chat chat = new Chat(baseUrl);
chat.loadMore();
assertEquals("hello, world!", chat.messages());
// Shut down the server. Instances cannot be reused.
server.shutdown();
}
希望这有帮助。
MockWebServer 在 AndroidTestCase 中对我不起作用。例如,ECONNDEND错误是随机发生的(在 https://github.com/square/okhttp/issues/1069 中描述)。我没有尝试Robolectric。
从 OkHttp 2.2.0 开始,我找到了一种适合我的替代方法:拦截器。我将整个模拟响应放在存储在androidTest/assets/
上的json文件中,例如"mock_response.json"。当我实例化一个 OkHttp 进行测试时,我暴露了一个拦截器,我将重写传入的响应。基本上,body() 会将数据流式传输到 'mock_response.json' 中。
public class FooApiTest extends AndroidTestCase {
public void testFetchData() throws InterruptedException, IOException {
// mock_response.json is placed on 'androidTest/assets/'
final InputStream stream = getContext().getAssets().open("mock_response.json");
OkHttpClient httpClient = new OkHttpClient();
httpClient.interceptors().add(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
return new Response.Builder()
.protocol(Protocol.HTTP_2)
// This is essential as it makes response.isSuccessful() returning true.
.code(200)
.request(chain.request())
.body(new ResponseBody() {
@Override
public MediaType contentType() {
return null;
}
@Override
public long contentLength() {
// Means we don't know the length beforehand.
return -1;
}
@Override
public BufferedSource source() {
try {
return new Buffer().readFrom(stream);
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
})
.build();
}
});
FooApi api = new FooApi(httpClient);
api.fetchData();
// TODO: Let's assert the data here.
}
}
Mockinizer可以更轻松地使用Mockinizer,这使得使用MockWebServer变得更加容易:
val mocks: Map<RequestFilter, MockResponse> = mapOf(
RequestFilter("/mocked") to MockResponse().apply {
setResponseCode(200)
setBody("""{"title": "Banana Mock"}""")
},
RequestFilter("/mockedError") to MockResponse().apply {
setResponseCode(400)
}
)
只需创建一个 RequestFilter 和 MockResponse 的映射,然后将其插入您的 OkHttpClient 构建器链:
OkHttpClient.Builder()
.addInterceptor(loggingInterceptor)
.mockinize(mocks) // <-- just plug in your custom mocks here
.build()