在Android上模拟服务器结果(Wiremock,MockWebServer等)

有没有人有关于记录服务器响应的完整和最近的教程或项目 – 根据需要获取和发布和标题并使用wiremock和/或mockwebserver播放它们?

我已经看过很多了

最佳答案 我在我目前的项目中实施了一个.首先,我创建了一个MockHTTPDispatcher类,它从OkHttp3扩展Dispatcher类.这里的Matcher是从Hamcrest进口的.

public class MockHTTPDispatcher extends Dispatcher {

    private Map<Matcher<RecordedRequest>, MockResponse> requestResponseMap;

    public MockHTTPDispatcher() {
        requestResponseMap = new HashMap<>();
    }

    public MockHTTPDispatcher mock(Matcher<RecordedRequest> matcher, MockResponse mockResponse) {
        requestResponseMap.put(matcher, mockResponse);
        return this;
    }

    @Override
    public MockResponse dispatch(RecordedRequest recordedRequest) {
        String recordedRequestPath = recordedRequest.getPath();
        for (Matcher<RecordedRequest> mockRequest : requestResponseMap.keySet()) {
            if (mockRequest.matches(recordedRequest)) {
                MockResponse response = requestResponseMap.get(mockRequest);
                return response;
            }
        }
        //means unable to find path for recordedRequestPath
        return new MockResponse().setResponseCode(404);
    }

    //you can also create a clear() method to clear the requestResponseMap if needed
}

然后,我创建了一个实现TestRule的MockWebServerRule类.这组代码将涵盖您想要设置标题但不需要时的情况.

public class MockWebServerRule implements TestRule {
    public static final String DOMAIN = "localhost";
    public static final int PORT = 4567;
    private MockHTTPDispatcher mockHTTPDispatcher;
    private MockWebServer mockWebServer;

    public MockWebServerRule() {
        mockWebServer = new MockWebServer();
        mockHTTPDispatcher = new MockHTTPDispatcher();
        mockWebServer.setDispatcher(mockHTTPDispatcher);
    }

    @Override
    public Statement apply(Statement statement, Description description) {
        return new MockHTTPServerStatement(statement);
    }

    public void mockResponse(String path, String httpMethod, int httpResponseCode, String response) throws Exception {
        mockResponseWithHeaders(path, httpMethod, httpResponseCode, response, null);
    }

    public void mockResponseWithHeaders(String path, String httpMethod, int httpResponseCode,
                                        String response, Headers headers) throws Exception {
        mock(allOf(pathStartsWith(path), httpMethodIs(httpMethod)), httpResponseCode, response, headers);
    }

    public void mock(Matcher<RecordedRequest> requestMatcher, int httpResponseCode, String response, Headers headers) throws IOException {
        MockResponse mockResponse = new MockResponse()
                .setResponseCode(httpResponseCode)
                .setBody(response);
        if (headers != null)
            mockResponse.setHeaders(headers);
        mockHTTPDispatcher.mock(requestMatcher, mockResponse);
    }

    public MockHTTPDispatcher getDispatcher() {
        return mockHTTPDispatcher;
    }

    //inner class for starting and shutting down localhost
    private class MockHTTPServerStatement extends Statement {

        private Statement base;

        public MockHTTPServerStatement(Statement base) {
            this.base = base;
        }

        @Override
        public void evaluate() throws Throwable {
            mockWebServer.start(PORT);
            try {
                this.base.evaluate();
            } finally {
                mockWebServer.shutdown();
            }
        }
    }
}

对于httpMethodIs和pathStartsWith,您需要在某处创建这样的方法(我为这些创建了一个名为RequestMatchers的类).

    public static Matcher<RecordedRequest> httpMethodIs(final String httpMethod) {
    return new TypeSafeMatcher<RecordedRequest>() {
        @Override
        protected boolean matchesSafely(RecordedRequest item) {
            return httpMethod.equals(item.getMethod());
        }

        @Override
        public void describeTo(org.hamcrest.Description description) {
            description.appendText("getMethod should return");
        }
    };
}

    public static Matcher<RecordedRequest> pathStartsWith(final String path) {
    return new TypeSafeMatcher<RecordedRequest>() {
        @Override
        protected boolean matchesSafely(RecordedRequest item) {
            return item.getPath().startsWith(path);
        }

        @Override
        public void describeTo(org.hamcrest.Description description) {
            description.appendText("getPath should return");
        }
    };
}

在您的检测测试中,您可以使用注释@Rule调用模拟Web服务器规则,如下所示:

public class YourActivityTest {

    @Rule
    public MockWebServerRule mockWebServerRule = new MockWebServerRule();

    @Test
    public void shouldHandleResponse200() throws Exception {
        mockWebServerRule.mockResponse("/your/api/endpoint/", "GET", 200, readAsset("response_success.json"));

        //your assertion here
    }
}

您可以使用“POST”或其他任何符合预期状态代码响应的“GET”进行更改.不要忘记在代码中的某处添加readAsset(String fileName)的实现,以便它可以读取您存储的json资产.

点赞