5

Does anyone have a full and recent tutorial or project on recording server responses- get and post and headers as needed AND Playing them back with wiremock and/or mockwebserver?

I've looked at many out there already

4

1 回答 1

2

我在我目前的项目中实施了一个。首先,我创建了一个从 OkHttp3MockHTTPDispatcher扩展类的类。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
}

然后,我创建了一个MockWebServerRule实现TestRule. 这一堆代码将涵盖您想要设置标题和不设置标题的情况。

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

对于httpMethodIsand 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,如下所示:

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

您可以使用预期的状态代码响应更改"GET"with"POST"或其他任何内容。不要忘记readAsset(String fileName)在您的代码中添加某个地方的实现,以便它可以读取您存储的 json 资产。

于 2016-09-06T17:53:39.250 回答