Как проверить, правильно ли установлены значения Apache HttpClient RequestConfig? Публичных добытчиков нет - PullRequest
0 голосов
/ 12 мая 2019

У меня есть этот класс для настройки экземпляра HttpClient:

package com.company.fraud.preauth.service.feignaccertifyclient;

    import com.company.fraud.preauth.config.ProviderClientConfig;
    import lombok.RequiredArgsConstructor;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.http.client.HttpClient;
    import org.apache.http.client.config.RequestConfig;
    import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
    import org.apache.http.impl.client.HttpClientBuilder;
    import org.apache.http.ssl.SSLContextBuilder;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;

    import java.security.KeyManagementException;
    import java.security.KeyStoreException;
    import java.security.NoSuchAlgorithmException;


    @Slf4j
    @Configuration
    @RequiredArgsConstructor
    public class FeignClientConfig {

        private final ProviderClientConfig providerClientConfig;

        public HttpClient buildHttpClient() throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
            RequestConfig.Builder requestBuilder = RequestConfig.custom();
            requestBuilder.setConnectTimeout(providerClientConfig.getConnectionTimeout());
            requestBuilder.setConnectionRequestTimeout(providerClientConfig.getConnectionRequestTimeout());
            requestBuilder.setSocketTimeout(providerClientConfig.getSocketTimeout());
            SSLContextBuilder builder = new SSLContextBuilder();
            builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());

            return HttpClientBuilder.create()
                    .setMaxConnPerRoute(providerClientConfig.getMaxConnectionNumber())
                    .setDefaultRequestConfig(requestBuilder.build())
                    .setSSLContext(builder.loadTrustMaterial(null, new TrustSelfSignedStrategy()).build())
                    .build();
        }
    }

Как провести модульное тестирование этого класса, чтобы увидеть в приведенном HttpClient, что эти значения установлены правильно?

С httpClient я не могу получить доступ к RequestConfig.

Мне известны следующие два сообщения:

Как проверить приватную функцию или класс, у которого есть закрытые методы, поля или внутренние классы? (Число upvotes в этом вопросе показывает, что она является одновременно и спорной темой в тестировании, и моя ситуация может привести пример, что почему мы должны смотреть на внутреннее состояние экземпляра в тестировании, несмотря на то что это частное)

Тайм-ауты модульного теста в Apache HttpClient (он показывает способ добавления перехватчика в код для проверки значений конфигурации, но мне это не нравится, потому что я хочу разделить тесты функциональными кодами)

Есть ли способ? Я понимаю, что этот класс должен быть проверен, верно? Вы не можете слепо доверить это работе; и проверка «notNull» кажется мне хрупкой.


Эта ссылка может указывать мне правильное направление:

https://dzone.com/articles/testing-objects-internal-state

Используется PowerMock.Whitebox для проверки внутреннего состояния экземпляра.

1 Ответ

0 голосов
/ 12 мая 2019

Итак, я зарегистрировался в PowerMock.Whitebox исходном коде, и оказалось, что отражение используется внутри.И поскольку PowerMock, как говорят, еще не совместим с JUnit 5 (до сих пор), и я не хочу добавлять другую зависимость только для тестирования, поэтому я буду тестировать с отражением.

package com.company.fraud.preauth.service.feignaccertifyclient;

import com.company.fraud.preauth.config.PreAuthConfiguration;
import com.company.fraud.preauth.config.ProviderClientConfig;
import com.company.fraud.preauth.config.StopConfiguration;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;

import java.lang.reflect.Field;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.when;

@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = {
        PreAuthConfiguration.class,
        StopConfiguration.class,
})
public class FeignClientConfigTest {

    @Mock
    private ProviderClientConfig providerClientConfig;

    @Test
    @DisplayName("should return HttpClient with defaultConfig field filled with values in providerClientConfig")
    public void shouldReturnHttpClientWithConfiguredValues() throws Exception {
        // given
        when(providerClientConfig.getConnectionRequestTimeout()).thenReturn(30000);
        when(providerClientConfig.getConnectionTimeout()).thenReturn(30);
        when(providerClientConfig.getMaxConnNumPerRoute()).thenReturn(20);
        when(providerClientConfig.getSocketTimeout()).thenReturn(10);
        FeignClientConfig feignClientConfig = new FeignClientConfig(providerClientConfig);

        // when
        HttpClient httpClient = feignClientConfig.buildHttpClient();

        // then
        // I want to test internal state of built HttpClient and this should be checked
        // I tried to use PowerMock.Whitebox, but then I found it uses reflection internally
        // I don't want to introduce another dependency, and PowerMock is said not to be compatible with JUnit 5, so..
        Field requestConfigField = httpClient.getClass().getDeclaredField("defaultConfig");
        requestConfigField.setAccessible(true);
        RequestConfig requestConfig = (RequestConfig)requestConfigField.get(httpClient);
        assertThat(requestConfig.getConnectionRequestTimeout(), equalTo(30000));
        assertThat(requestConfig.getConnectTimeout(), equalTo(30));
        assertThat(requestConfig.getSocketTimeout(), equalTo(10));
    }

}

Также, Я отвечаю на первый вопрос в OP о том, когда тестировать частных членов в классе здесь

...