问题
I'm using spring-boot
with WebClient
, which is autowired as a bean.
Problem: when writing a junit
integration test, I have to use okhttp MockWebServer
. This mock always starts up on a random port, eg localhost:14321
.
Now my WebClient
of course has a fixed url that it sends the requests to. This url may be given by an application.properties
parameter like webclient.url=https://my.domain.com/
, so I could override that field in a junit
test. But only statically.
Question: how can I reset the WebClient
bean inside a @SpringBootTest
so that it sends the requests always to my mock server?
@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();
}
}
As you see, I'm writing a full realworld junit integration test. The only problem is: how can I pass the MockWebServer
url and port to the WebClient
so that it automatically sends the requests to my mock??
Sidenote: I definitely need a random port in MockWebServer
here to not interfer with other running tests or applications. Thus have to stick to the random port, and find a way to pass it to the webclient (or dynamically override the application property).
Update: I came up with the following, which works. But maybe anyone knows how to make the mockserver field non-static?
@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:
You can use the method setField(Object targetObject, String name, Object value)
from ReflectionTestUtils.
@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()....);
WebClientService newWebClientService = new WebClientService(WebClient.builder(), mockWebServer.url("/").toString());
ReflectionTestUtils.setField(calling, "service", newWebClientService);
calling.call();
}
来源:https://stackoverflow.com/questions/57186938/how-to-set-mockwebserver-port-to-webclient-in-junit-test