У меня есть служба, над которой я издеваюсь:
@ExtendWith(MockitoExtension.class)
class MyServiceTest {
@InjectMocks
MyService myService;
@Test
void testSendRec() {
myService.sendDocRec(.. pass params..);
}
}
обслуживание:
@Service
public class MyService {
String sendDocRec( params ) {
// builds request
HttpUriRequestBase request = getRequest( params );
String response = doRequest(request);
}
public String doRequest(ClassicHttpRequest request) {
String result = null;
try (CloseableHttpClient httpclient = HttpClients.custom()
.setConnectionManager(this.connectionManager)
.setConnectionManagerShared(true)
.setDefaultRequestConfig(this.requestConfig)
.build()) {
final HttpClientContext clientContext = HttpClientContext.create();
try (CloseableHttpResponse response = httpclient.execute(request, clientContext)) {
result = EntityUtils.toString(response.getEntity());
}
} catch (URISyntaxException e) {
log.error("Invalid URI {}", e);
} catch (IOException e) {
log.error("Failed to make HTTP Request {}", e);
} catch (ParseException e) {
log.error("Failed parsing response body {}", e);
}
return result;
}
}
Мне нужно иметь возможность издеваться над «CloseableHttpResponse response = httpclient.execute(request, clientContext)», чтобы объект «ответ» был чем-то, что я создаю заранее. Я надеюсь, что некоторые издевательские конструкции, когда/тогда, будут работать для этого? Буду признателен за идеи как это сделать. Спасибо!
HttpClient
в другой класс и экземпляр этого класса будет внедрен в ваш класс, тестирование станет простым.
Вы не можете сделать это, используя текущую структуру кода. Объект httpclient создается в тестируемом методе. Так что издеваться нельзя.
Вам нужно делегировать создание объекта httpclient другому методу, принадлежащему другому классу (что-то похожее на класс HttpClientFactory). Этот класс HttpClientFactory должен отвечать только за создание экземпляров httpClient. Если вам нужно, вы можете написать отдельный тестовый пример для класса.
@Inject
private HttpClientFactory httpClientFactory;
public String doRequest(ClassicHttpRequest request) {
String result = null;
try (CloseableHttpClient httpclient = httpClientFactory.getInstance()) {
final HttpClientContext clientContext = HttpClientContext.create();
try (CloseableHttpResponse response = httpclient.execute(request, clientContext)) {
result = EntityUtils.toString(response.getEntity());
}
} catch (URISyntaxException e) {
log.error("Invalid URI {}", e);
} catch (IOException e) {
log.error("Failed to make HTTP Request {}", e);
} catch (ParseException e) {
log.error("Failed parsing response body {}", e);
}
return result;
}
Теперь вы можете имитировать ответ, как показано ниже:
@Mock
private HttpClientFactory httpClientFactory;
public String testDoRequest(ClassicHttpRequest request) {
....
CloseableHttpClient mockedClient = mock(CloseableHttpClient.class);
CloseableHttpResponse mockedResponse = mock(CloseableHttpResponse.class);
when(httpClientFactory.getInstance()).thenReturn(mockedClient);
when(mockedClient.execute(eq(request), any(clientContext))).thenReturn(mockedResponse);
....}
спасибо, но я смущен этим. Является ли метод @Inject и doRequest(), который вы показываете, рефакторингом doRequest() в классе MyService?
также, где мой метод sendDocRec(), который был исходным вызванным методом? Я потерял контекст против моего первоначального вопроса. Спасибо
первый комментарий: ответ да, рефакторинг doRequest() в классе MyService. второй комментарий: sendDocRec() по-прежнему будет частью MyService и останется неизменным. я не добавлял, так как не было никаких изменений. Вероятно, это вызвало недоумение. Я просто хотел показать части, которые я бы изменил.
вы, кажется, пропустили ConnectionManager и requestConfig...? Просто слишком много сокращений для меня. Очевидно, вы предполагаете, что у меня есть навыки, чтобы заполнить дыры. Спасибо, в любом случае...
Вы ничего не издеваетесь. Кроме того, поскольку
HttpClient
настроен внутри метода, вы не можете его имитировать. Вместо этого вы должны ввести его таким образом, чтобы вы могли издеваться над ним. Или используйте пружинуRestTemplate
илиWebClient
и настройте это с помощью HTTP-клиента Apache и используйте для этого поддержку тестирования/насмешки.