I'm having difficulty in creating a valid test for a webflux controller that returns a Flux on one second intervals. I have probably been close a couple of times in my many attempts, but there is always something amiss and I haven't been able to stumble upon a solution.
The controller:
@RestController
public class SWFluxDemoController {
@Autowired
SWFluxDemoService swFluxDemoService;
// Messages are Sent to the client as Server Sent Events
@GetMapping(value = "/", produces = MediaType.TEXT_HTML_VALUE)
public Flux<String> pushEventSignal() {
return swFluxDemoService.getInfinityString();
}
}
The Service:
@Service
public class SWFluxDemoService {
public Flux<String> getInfinityString() {
Flux<Long> interval = Flux.interval(Duration.ofSeconds(1));
interval.subscribe((i) -> generateNewMessage());
Flux<String> messageFlux = Flux.fromStream(
Stream.generate(() -> generateNewMessage()));
return Flux.zip(interval, messageFlux).map(Tuple2::getT2);
}
private String generateNewMessage() {
Date theDate = new Date();
String newMessage = "Updated response at: " + theDate.toString() + "<BR>";
return newMessage;
}
}
The Web Client:
public class SimpleFluxClient {
public static void main(String[] args) throws InterruptedException {
WebClient webClient = WebClient.create("http://localhost:8080");
Mono<String> result = webClient.get().retrieve().bodyToMono(String.class);
}
}
If I run this on the command line with mvn spring-boot:run and then hit the url localhost:8080 in my browser, I will get the response:
Updated response at: Wed Mar 07 16:09:55 EST 2018
Updated response at: Wed Mar 07 16:09:56 EST 2018
Updated response at: Wed Mar 07 16:09:57 EST 2018
Updated response at: Wed Mar 07 16:09:58 EST 2018
which is what I want.
The issue is writing and executing a test in the Spring Tool Suite. I want to do something similar to the following, but this won't pass a syntax check let alone run.
@RunWith(SpringRunner.class)
@ContextConfiguration(classes={SWFluxDemoController.class,SWFluxDemoService.class})
@WebFluxTest(controllers=SWFluxDemoController.class)
public class SimpleWebFluxDemoApplicationTests {
@Autowired
private WebTestClient webClient;
@Test
public void get() throws Exception{
FluxExchangeResult<String> result = webClient.get().uri("/").accept(MediaType.TEXT_EVENT_STREAM)
.exchange()
// .expectStatus().isCreated()
.returnResult(String.class);
StepVerifier.withVirtualTime({ result })
.expectSubscription()
.thenAwait(Duration.ofSeconds(1))
.expectNext(0);
}
}
Coding any expected status for the webclient call with the StepVerifier code commented out returns a <406> error No content available.
Any help greatly appreciated.
Your controller declares that it produces TEXT_HTML_VALUE
; whereas, your test declares that it accepts TEXT_EVENT_STREAM
.
That's what leads to the 406 response code.
So you'll need to ensure that the produces and accepts media types are compatible.
After mucking around I finally arrived at a solution. My test ended up as follows:
@Test
public void get() throws Exception{
FluxExchangeResult<String> result = webClient.get().uri("/").accept(MediaType.TEXT_EVENT_STREAM)
.exchange()
.returnResult(String.class);
Flux<String> intervalString = result.getResponseBody();
StepVerifier.create(intervalString)
.expectSubscription()
.thenAwait(Duration.ofSeconds(1))
.expectNextCount(0)
.thenAwait(Duration.ofSeconds(1))
.expectNextCount(1)
.thenAwait(Duration.ofSeconds(1))
.expectNextCount(2);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.