Подтвердить что ты не робот

Как код unit test, который вызывает API-интерфейс Jersey Client?

Я написал код, который вызывает API-интерфейс клиента Jersey, который, в свою очередь, вызывает веб-сервис, который не поддается контролю. Я не хочу, чтобы мой unit test вызывал фактическую веб-службу.

Каков наилучший подход для написания кода unit test для кода, который вызывает API-интерфейс клиента Jersey? Должен ли я использовать API-интерфейс Джерси для создания веб-службы JAX-RS, а затем использовать тестовую платформу Джерси для unit test? Или я должен высмеивать звонки веб-службы Джерси? У меня есть доступ к JMock. Или я должен попробовать другой подход?

Во время моего исследования я нашел это обсуждение, описывающее различные варианты, но я нашел полное решение. Существуют ли примеры кода, показывающие предлагаемый подход JUnit? Я не мог найти ни одного документа в Джерси.

Вот соответствующий исходный код:

public String getResult(URI uri) throws Exception {
  // error handling code removed for clarity
  ClientConfig clientConfig = new DefaultClientConfig();
  Client client = Client.create(clientConfig);
  WebResource service = client.resource(uri);
  String result = service.accept(accept).get(String.class);
  return result;
}

Вот примеры тестового кода, который я хотел бы передать. Я хотел бы протестировать (1), проходящий в допустимом URI и вернув правильную строку, и (2) передать недопустимый (по какой-либо причине - недостижимый или неавторизованный) URI и получить исключение.

@Test
public void testGetResult_ValidUri() throws Exception {
  String xml = retriever.getResult(VALID_URI);
  Assert.assertFalse(StringUtils.isBlank(xml));
}

@Test(expected = IllegalArgumentException.class)
public void testGetResult_InvalidUri() throws Exception {
  retriever.getResult(INVALID_URI);
}

Все вышеизложенное - это простое описание того, что делает мой код. На самом деле есть слой поверх того, который принимает два URI, сначала пытается вызвать первый URI, и если этот URI терпит неудачу, он пытается вызвать второй URI. Я хотел бы иметь модульные тесты, охватывающие (1), первый URI преуспевает, (2) сбой первого URI и второй URI преуспевает, и (3) оба URI не работают. Этот код достаточно сложный, поэтому я хочу протестировать эти разные сценарии с помощью JUnit, но для этого мне нужно либо запустить реальные веб-службы в режиме ожидания, либо высмеять вызовы API-клиентов Джерси.

4b9b3361

Ответ 1

Попробуйте использовать Mockito или Easymock для издевательских вызовов. Вам нужно высмеять только те методы, которые фактически используются - не нужно издеваться над каждым методом. Вы можете создать mock-объект для класса WebResource, а затем moker принять вызов метода.

В @BeforeClass/@Прежде чем использовать метод тестирования JUnit, напишите что-нибудь вроде (пример Mockito)

WebResource res = mock(WebResource.class);
when(res.accept(something)).thenReturn(thatWhatYouWant);

Затем в ваших тестах вы можете использовать объект res, как если бы это был реальный объект, и на нем вызывается метод mock. Вместо того, чтобы возвращать значение, вы также можете генерировать исключения. Mockito довольно круто.

Ответ 2

Как правило, на самом деле вы на самом деле следуете "делает ли я, используя DSL-клиент Джерси запрос на правильный URL с правильными параметрами полезной нагрузки и URL". Тестирование этого с помощью Mockito действительно многословно, и установочный код обычно будет выглядеть примерно так:

    when(authentication.queryParam(eq("sa"), anyBoolean())).thenReturn(testAuthentication);
    when(testAuthentication.resolveTemplate("channel", "smf")).thenReturn(testAuthentication);
    when(testAuthentication.request(
            MediaType.APPLICATION_JSON_TYPE)).thenReturn(mockRequestBuilder);
    when(mockRequestBuilder.post(any(Entity.class))).thenReturn(mockResponse);
    when(mockResponse.readEntity(ResponseWrapper.class)).thenReturn(successfulAuthResponse());

И это в основном только для одного запроса REST. Это слишком многословный вариант, и вместо проверки ожидаемого результата вы просто копируете шаги, которые, по вашему мнению, правильны при использовании DSL-клиента Jersey.

Вместо вышесказанного я бы постарался насмехаться над простым сервисом. Для этого я использовал WireMock, который запускает сервер Jetty, и где я могу заглушить такие вещи, как "ожидать запроса на этот URL-адрес", это сообщение и убедитесь, что это полезная нагрузка ".

Я знаю, что это окантовка в тесте интеграции, и это немного медленнее, чем просто использование Mockito, но я ценю тестирование реального результата, и в этом случае я больше понимаю читаемость тестов.

Настройка для теста на клиентский интерфейс на основе WireMock выглядит примерно так:

@Test
public void exactUrlOnly() {
    stubFor(get(urlEqualTo("/some/thing"))
            .willReturn(aResponse()
                .withHeader("Content-Type", "text/plain")
                .withBody("Hello world!")));

   assertThat(testClient.get("/some/thing").statusCode(), is(200));
   assertThat(testClient.get("/some/thing/else").statusCode(), is(404));
}

Ответ 3

Просто выполните сервисный сервис и в настройке unit test запустите службу с помощью HttpServerFactory.