Насмешка над вложенным объектом в Junit

У меня есть служба, над которой я издеваюсь:

@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 настроен внутри метода, вы не можете его имитировать. Вместо этого вы должны ввести его таким образом, чтобы вы могли издеваться над ним. Или используйте пружину RestTemplate или WebClient и настройте это с помощью HTTP-клиента Apache и используйте для этого поддержку тестирования/насмешки.

M. Deinum 21.11.2022 17:03
Почему мой класс не вызывает мои фиктивные методы в модульном тесте? делится полезными мыслями (и решением вашей проблемы тоже). Если вы переместите создание своего HttpClient в другой класс и экземпляр этого класса будет внедрен в ваш класс, тестирование станет простым.
knittl 27.11.2022 11:02
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Как включить TLS в gRPC-клиенте и сервере : 2
Как включить TLS в gRPC-клиенте и сервере : 2
Здравствуйте! 🙏🏻 Надеюсь, у вас все хорошо и добро пожаловать в мой блог.
Сортировка hashmap по значениям
Сортировка hashmap по значениям
На Leetcode я решал задачу с хэшмапой и подумал, что мне нужно отсортировать хэшмапу по значениям.
Принципы SOLID - лучшие практики
Принципы SOLID - лучшие практики
SOLID - это аббревиатура, обозначающая пять ключевых принципов проектирования: принцип единой ответственности, принцип "открыто-закрыто", принцип...
gRPC на Android с использованием TLS
gRPC на Android с использованием TLS
gRPC - это относительно новая концепция взаимодействия между клиентом и сервером, но не более.
0
2
64
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы не можете сделать это, используя текущую структуру кода. Объект 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?

Timothy Clotworthy 21.11.2022 17:44

также, где мой метод sendDocRec(), который был исходным вызванным методом? Я потерял контекст против моего первоначального вопроса. Спасибо

Timothy Clotworthy 21.11.2022 18:09

первый комментарий: ответ да, рефакторинг doRequest() в классе MyService. второй комментарий: sendDocRec() по-прежнему будет частью MyService и останется неизменным. я не добавлял, так как не было никаких изменений. Вероятно, это вызвало недоумение. Я просто хотел показать части, которые я бы изменил.

aatwork 21.11.2022 18:21

вы, кажется, пропустили ConnectionManager и requestConfig...? Просто слишком много сокращений для меня. Очевидно, вы предполагаете, что у меня есть навыки, чтобы заполнить дыры. Спасибо, в любом случае...

Timothy Clotworthy 21.11.2022 18:33

Другие вопросы по теме