Add an example with WEBTESTCLIENT & RouterFunction
AndersClausen opened this issue · 1 comments
Would it be possible to add an example of how to set up spring-cloud-contracts for it to work with a RouterFunction in a WebFlux style (please see code below)? I'm particular interested in seeing how the BaseTest class looks like - by that I mean, how is RestAssuredWebTestClient set up, what annotations are used and how much mocking of objects are required.
@Configuration
public class LocationRouter {
private ReactiveErrorHandler error = new ReactiveErrorHandler();
@Bean
public RouterFunction<ServerResponse> route(LocationHandler handler) {
return RouterFunctions.route(GET("/locations"), handler::getLocations)
.andRoute(GET("/locations/{geoId}"), handler::getLocationsByGeoId)
.filter(error.notFound())
.filter(error.badRequest())
.filter(error.catchAll());
}
}
The problem at hand
I cannot get past this error message
java.lang.IllegalStateException: Failed to load ApplicationContext
I have tried a set up like this in my BaseTest class:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
public abstract class LocationBaseTest {
@Autowired
WebApplicationContext webAppContext;
@Autowired
ApplicationContext appContext;
@Before
public void setup() {
// RestAssuredWebTestClient.applicationContextSetup(appContext);
// RestAssuredWebTestClient.webAppContextSetup(webAppContext);
RestAssuredWebTestClient.standaloneSetup(new LocationRouter());
}
}
The commented out lines in the code above are the other options I've tried.
I've also tried to use
@MockBean LocationHandler handler
but that didn't get me anywhere.
Router function configuration
@Configuration
public class ProducerConfiguration {
private final PersonCheckingService personCheckingService;
public ProducerConfiguration(PersonCheckingService personCheckingService) {
this.personCheckingService = personCheckingService;
}
// remove::start[]
@Bean
public RouterFunction<ServerResponse> route() {
return RouterFunctions.route(RequestPredicates.POST("/check")
.and(RequestPredicates.contentType(MediaType.APPLICATION_JSON)),
request -> this.check(request));
}
private Mono<ServerResponse> check(ServerRequest request) {
return request.bodyToMono(PersonToCheck.class)
.flatMap(person -> {
if (this.personCheckingService.shouldGetBeer(person)) {
return Mono.just(new Response(BeerCheckStatus.OK));
}
return Mono.just(new Response(BeerCheckStatus.NOT_OK));
})
.flatMap(res -> ServerResponse.ok().bodyValue(res));
}
// remove::end[]
}
interface PersonCheckingService {
Boolean shouldGetBeer(PersonToCheck personToCheck);
}
class PersonToCheck {
public int age;
public PersonToCheck(int age) {
this.age = age;
}
public PersonToCheck() {
}
}
class Response {
public BeerCheckStatus status;
Response(BeerCheckStatus status) {
this.status = status;
}
}
enum BeerCheckStatus {
OK, NOT_OK
}
Base class setup
package com.example;
import io.restassured.module.webtestclient.RestAssuredWebTestClient;
import org.junit.Before;
import org.springframework.test.web.reactive.server.WebTestClient;
public abstract class BeerRestBase {
@Before
public void setup() {
//remove::start[]
RestAssuredWebTestClient.webTestClient(WebTestClient.bindToRouterFunction(
new ProducerConfiguration(personToCheck -> personToCheck.age >= 20).route()).build());
// remove::end[]
}
}