Результаты имитации сервера на Android (Wiremock, MockWebServer и т. д.)

Есть ли у кого-нибудь полный и недавний учебник или проект по записи ответов сервера - получайте и публикуйте и заголовки по мере необходимости И воспроизводите их с помощью wiremock и/или mockwebserver?

Я уже много где посмотрел


person nAndroid    schedule 20.06.2016    source источник
comment
как вы уже просмотрели многие, что вам еще не хватает?   -  person kalin    schedule 03.09.2016
comment
На wiremock.org/docs/record-playback вы найдете базовое руководство по записи и воспроизводить http-сообщения. Пожалуйста, спрашивайте более конкретно, если у вас есть проблемы с шагом.   -  person nenick    schedule 04.09.2016


Ответы (1)


Я реализовал один в моем текущем проекте. Прежде всего, я создал класс MockHTTPDispatcher, который расширяет класс Dispatcher из OkHttp3. 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();
            }
        }
    }
}

Для 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, вот так:

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" на "POST" или что-то еще с ожидаемым ответом кода состояния. Не забудьте добавить реализацию readAsset(String fileName) где-нибудь в свой код, чтобы он мог читать ресурсы json, которые вы сохранили.

person baskara    schedule 06.09.2016