如何在JUnit测试中将MockWebServer端口设置为WebClient?

我使用与 ,它是自动连接为豆类。spring-bootWebClient

问题:在编写集成测试时,我必须使用 okhttp 。此模拟始终在随机端口上启动,例如 。junitMockWebServerlocalhost:14321

现在我当然有一个固定的URL,它可以发送请求。这个url可以由一个参数给出,比如,所以我可以在测试中覆盖这个字段。但只是静态的。WebClientapplication.propertieswebclient.url=https://my.domain.com/junit

问:如何重置 a 中的 Bean,以便它始终将请求发送到我的模拟服务器?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();
        }
}

如您所见,我正在编写一个完整的真实世界 junit 集成测试。唯一的问题是:如何将url和端口传递给,以便它自动将请求发送到我的模拟?MockWebServerWebClient

旁注:我绝对需要一个随机端口,以免干扰其他正在运行的测试或应用程序。因此,必须坚持使用随机端口,并找到一种方法将其传递给Web客户端(或动态覆盖应用程序属性)。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());
        }
    }
}

答案 1

从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();
    }
}

答案 2

推荐