programing

Junit 테스트에서 MockWebServer 포트를 WebClient로 설정하는 방법은 무엇입니까?

mailnote 2023. 6. 30. 22:32
반응형

Junit 테스트에서 MockWebServer 포트를 WebClient로 설정하는 방법은 무엇입니까?

사용 중spring-boot와 함께WebClient그것은 콩처럼 자동으로 연결되어 있습니다.

문제: a를 작성할 때junit통합 테스트, 나는 okhttp를 사용해야 합니다.MockWebServer이 모의실험은 항상 랜덤 포트에서 시작됩니다. 예를 들어localhost:14321.

이제 나의WebClient물론 요청을 보내는 고정 URL이 있습니다.이 URL은 다음과 같이 지정할 수 있습니다.application.properties매개 변수와 같은webclient.url=https://my.domain.com/그래서 나는 그 분야를 무시할 수 있었습니다.junit테스트. 하지만 정적으로만.

질문: 어떻게 재설정할 수 있습니까?WebClient마음속에 있는@SpringBootTest항상 제 모의 서버로 요청을 보내도록 해야 합니까?

@Service
public class WebClientService {
     public WebClientService(WebClient.Builder builder, @Value("${webclient.url}" String url) {
          this.webClient = builder.baseUrl(url)...build();
     }

     public Response send() {
          return webClient.body().exchange().bodyToMono();
     }
}

@Service
public void CallingService {
      @Autowired
      private WebClientService service;

      public void call() {
           service.send();
      }
}


@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class MyWebTest {
        @Autowired
        private CallingService calling;

        @Test
        public void test() {
             MockWebServer mockWebServer = new MockWebServer();
             System.out.println("Current mock server url: " + mockWebServer.url("/").toString()); //this is random    

             mockWebServer.enqueue(new MockResponse()....);

             //TODO how to make the mocked server url public to the WebClient?
             calling.call();
        }
}

보시다시피, 저는 완전한 실제 세계 통합 테스트를 작성하고 있습니다.유일한 문제는 어떻게 통과할 수 있는가 하는 것입니다.MockWebServer에 대한 URL 및 포트WebClient그러면 자동으로 요청이 내 모의실험으로 전송되는 건가요?

참고 사항:나는 확실히 무작위 포트가 필요합니다.MockWebServer다른 실행 중인 테스트 또는 응용 프로그램을 방해하지 않기 위해 여기에 있습니다.따라서 랜덤 포트를 고수하고 웹 클라이언트에 전달(또는 애플리케이션 속성을 동적으로 재정의)하는 방법을 찾아야 합니다.


업데이트: 저는 다음과 같은 것을 생각해냈습니다.하지만 모의 서버 필드를 정적이 아닌 상태로 만드는 방법을 아는 사람이 있을까요?

@ContextConfiguration(initializers = RandomPortInitializer.class)
public abstract class AbstractITest {
    @ClassRule
    public static final MockWebServer mockWebServer = new MockWebServer();

    public static class RandomPortInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
        @Override
        public void initialize(ConfigurableApplicationContext applicationContext) {
            TestPropertySourceUtils.addInlinedPropertiesToEnvironment(applicationContext,
                    "webclient.url=" + mockWebServer.url("/").toString());
        }
    }
}

Spring Framework 5.2.5(Spring Boot 2.x) 이후에는DynamicPropertySource아주 편리한 주석

다음은 사용할 수 있는 완전한 예입니다.MockWebServer올바른 포트를 바인딩하려면:

@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
public abstract class AbstractIT {

    static MockWebServer mockWebServer;

    @DynamicPropertySource
    static void properties(DynamicPropertyRegistry r) throws IOException {
        r.add("some-service.url", () -> "http://localhost:" + mockWebServer.getPort());
    }

    @BeforeAll
    static void beforeAll() throws IOException {
        mockWebServer = new MockWebServer();
        mockWebServer.start();
    }

    @AfterAll
    static void afterAll() throws IOException {
        mockWebServer.shutdown();
    }
}

MockWebServer의 URL로 WebClient 기본 URL을 설정할 수 있습니다.

WebClient 및 MockWebServer는 각 테스트에 대해 다시 생성할 수 있을 정도로 충분히 가볍습니다.

@SpringBootTest
class Tests {

  @Autowired
  private WebClient.Builder webClientBuilder;

  private MockWebServer mockWebServer;

  private WebClient client;

  @BeforeEach
  void setUp() throws Exception {
    mockWebServer = new MockWebServer();
    mockWebServer.start();

    // Set WebClinet base URL with the the mock web server URL 
    webClientBuilder.baseUrl(mockWebServer.url("").toString());

    client = webClientBuilder.build();

  }

  @AfterEach
  void tearDown() throws Exception {
    mockWebServer.shutdown();
  }

  @Test
  void bodyIsExpected() throws InterruptedException {

    mockWebServer.enqueue(new MockResponse().setStatus("HTTP/1.1 200 OK").setBody("Hello World!")
        .addHeader("Content-Type", "text/plain"));

    ResponseEntity<String> response = client.get().retrieve().toEntity(String.class).block();

    assertThat(response.getBody(), is("Hello World!"));
  }
}

언급URL : https://stackoverflow.com/questions/57186938/how-to-set-mockwebserver-port-to-webclient-in-junit-test

반응형