luchob / softuni-spring-may-2024

Our common projects
15 stars 1 forks source link

Проблем с integration test с WireMock #65

Closed ChrisHartarski closed 3 months ago

ChrisHartarski commented 3 months ago

Проект: https://github.com/ChrisHartarski/MagnaTechnica-WebShop-SoftUniProject

Кратко описание:

Какво всъщност се случва: Когато стартирам всички тестове заедно в test/.../service/impl/MachineServiceImplIT всички тестове минават. Когато пусна само теста testAddMachine() отделно получавам следната грешка: I/O error on POST request for "http://localhost:55703/test-machines/machines/add": EOF reached while reading

Какво поражда тази грешка? Как мога да я избегна? Защо се получава само когато пусна теста отделно? Благодаря!

luchob commented 3 months ago

Здрасти!

Добре дошъл в света на софтуерните "quirks" :-) Те ще те съпътстват във всеки един малко по-сериозен проект в произволна технология.

Този път, проблемът е следният. Както казахме "вътре" в RestClient-a има библиотека (Http Client), която се използва за правенето на самите заявки на по ниско ниво. В твоя проект това би трябвало да е JDK клиента. Само че, той по подразбиране ползва HTTP/2 с fallback към HTTP/1.1. Wiremock, който пуска HTTP server (може би jetty) поддържа този fallback доста лошо, поне в някои заявки като POST. Тук мисля, че е тракнато някакво issue. Та какво става - когато пуснеш само този тест, RestClient-a опитва POST с Http/2, и като не успява (wiremock работи с 1.1) опитва fallback към 1.1. Този fallback към HTTP/1.1 се чупи доста грозно и това е което ти виждаш. При GET заявката същия fallback минава и понеже като пуснеш всички тестове наведнъж първо минават GET заявките в един отворен конекшън, fallback-a сработва. :-) Малко е тъжно, но... :-)

Как най-лесно може да го оправиш? По много начини, но например в production и test application.propeties файловете може да добавиш следните редове, съотвено:

rest.configuration=prod

и в другия

rest.configuration=test

После в RestConfig-a:

@Configuration
public class RestConfig {

    @ConditionalOnProperty(value="rest.configuration", havingValue="prod")
    @Bean("machinesRestClient")
    public RestClient restClient(MachinesApiConfig machinesApiConfig) {
        return RestClient
                .builder()
                .baseUrl(machinesApiConfig.getBaseUrl())
                .defaultHeader("Accept", "application/json")
                .defaultHeader("Content-Type", "application/json")
                .build();
    }
}

И в само в test модула добави още един configuration:

@Configuration
public class TestRestConfig {

  @ConditionalOnProperty(value="rest.configuration", havingValue="test")
  @Bean("machinesRestClient")
  public RestClient restClient() {

    var client = HttpClient.newBuilder().version(HttpClient.Version.HTTP_1_1).build();
    var requestFactory = new JdkClientHttpRequestFactory(client);

    return RestClient
        .builder()
        .requestFactory(requestFactory)
        .build();
  }

}

Поздрави, Л.

ChrisHartarski commented 3 months ago

Благодаря, с тези настройки вече работи както трябва.