如何将TestScheduler与RxNetty http服务器

时间:2015-12-22 00:56:00

标签: java rx-java rx-netty

我正在尝试创建一个模拟服务器,以帮助更轻松地为在事件流上运行的客户端编写测试。

我正在使用RxNetty实现服务器和客户端,我的问题是我如何使用带有RxNetty的TestScheduler来控制何时发出事件。

这是我的(简化)服务器:

    final Observable<Event> events = Observable.just(...);
    final TestScheduler testScheduler = new TestScheduler();
    final HttpServer<ByteBuf, ByteBuf> server = RxNetty.createHttpServer(0, (request, response) -> {

        // [snip] validate request...

        return request.getContent().flatMap(buf ->
            events
                .zipWith(Observable.interval(10, TimeUnit.MILLISECONDS, testScheduler), (e, t) -> e)
                .map(Encoder::eventToBytes)
                .flatMap(response::writeBytesAndFlush)
        );
    });
    server.start();

但是,当我指定interval应该使用testScheduler时,服务器永远不会发送任何事件。如果我删除了testSchedulerSchedulers.computation()Schedulers.io(),则服务器可以发送事件。

以下是期望接收来自服务器的事件的客户端/使用方:

    final int serverPort = server.getServerPort();
    final URI uri = URI.create(String.format("http://localhost:%d/api/v1/scheduler", serverPort));
    final HttpClient<ByteBuf, ByteBuf> client = RxNetty.<ByteBuf, ByteBuf>newHttpClientBuilder(uri.getHost(), uri.getPort())
        .pipelineConfigurator(new HttpClientPipelineConfigurator<>())
        .build();

    final Event event = new Event("some event")

    final TestScheduler clientReceiveScheduler = new TestScheduler();
    final HttpClientRequest<ByteBuf> request = HttpClientRequest.createPost(uri.getPath())
        .withHeader("Content-Type", "application/x-protobuf")
        .withHeader("Accept", "application/x-protobuf")
        .withContent(event.toByteArray());

    final Observable<byte[]> observable = client.submit(request)
        .flatMap(AbstractHttpContentHolder::getContent)
        .map(BufUtils::bufToBytes)
        .zipWith(Observable.interval(10, TimeUnit.MILLISECONDS, clientReceiveScheduler), (b, l) -> b)
        .doOnNext((b) -> LOGGER.info("Received bytes: {}", Arrays.toString(b)));

    final TestSubscriber<Event> sub = new TestSubscriber<>();
    observable.subscribe(sub);

    testScheduler.advanceTimeBy(10, TimeUnit.MILLISECONDS);
    clientReceiveScheduler.advanceTimeBy(10, TimeUnit.MILLISECONDS);
    sub.getOnNextEvents()
        .stream()
        .forEach(System.out::println);

以下是我的full servertest case尝试使用该服务器的链接。

1 个答案:

答案 0 :(得分:0)

TestScheduler要求您使用其advanceTime*方法提前计划以触发任何计划的操作。 Observable.interval()计划对提供的调度程序执行操作,在本例中为TestScheduler。如果不在TestScheduler中推进时间,它将永远不会执行操作;在这种情况下,勾选Observable.interval()

如果查看此代码,请删除RxNetty:

    TestScheduler scheduler = Schedulers.test();
    TestSubscriber<Long> subscriber = new TestSubscriber<>();
    Observable.interval(1, TimeUnit.MILLISECONDS, scheduler)
              .take(1)
              .subscribe(subscriber);

    scheduler.advanceTimeBy(1, TimeUnit.MILLISECONDS);

    System.out.println(subscriber.getOnNextEvents().size());

输出将始终为1. OTOH,如果您注释掉scheduler.advanceTimeBy(1, TimeUnit.MILLISECONDS);,它将始终为0.