RxJava-如何使用“内部”测试函数;toBlocking";呼叫

RxJava-如何使用“内部”测试函数;toBlocking";呼叫,java,observable,rx-java,reactive-programming,Java,Observable,Rx Java,Reactive Programming,我试图在下面的代码中添加一些单元测试: public List<Stuff> extractStuff(Scheduler scheduler, List<Token> tokens) { List<Observable<List<Stuff>>> observables = tokens .stream() .map(token-> Observable.just(getS

我试图在下面的代码中添加一些单元测试:

public List<Stuff> extractStuff(Scheduler scheduler, List<Token> tokens) {
    List<Observable<List<Stuff>>> observables = tokens
            .stream()
            .map(token-> Observable.just(getStuffByToken(token)).subscribeOn(scheduler))
            .collect(Collectors.toList());

    List<Stuff> result = new ArrayList<>();
    for (List<Stuff> stuff: Observable.merge(observables).toBlocking().toIterable()) {
        result.addAll(stuff);
    }

    return result;
}
使用调试器,我可以看到
可观察。只是(…)
看起来不错(我的可观察列表不是空的,我可以在里面看到我的自定义模拟对象)

问题:执行似乎停留在
Observable.merge(observables).toblock()表达式上。永远不会调用行
result.addAll

我用
TestScheduler
对象尝试了几种方法,但无法使其正常工作。我在互联网上找到的大多数例子都是处理一个返回
可观察对象的函数,因此关联的单元测试可以运行
调度程序。advanceTimeBy(…)。在我的情况下,我不能应用这种方法,因为
可观察的
对象不能直接返回


非常感谢你的帮助

我不确定发布的代码是否按照您期望的方式运行。您的
getStuffByToken(…)
方法实际上是在调用线程上调用的,而不是由
调度程序调用的

为了简单起见,让我将
标记
替换为
整数
,将
填充
替换为
字符串

我的
getStuffByToken(…)
将返回
整数的
字符串
表示形式,并且还将包括当前
线程的名称:

private List<String> getStuffByToken( Integer token )
{
    return Arrays.asList( token.toString(), Thread.currentThread().getName() );
}
如果我们测试上述各项:

@Test
public void testExtractStuff()
{
    List<Integer> tokens = Arrays.asList( 1, 2, 3, 4, 5 );
    List<String> result = extractStuff( Schedulers.computation(), tokens );
    System.out.println( result );
}
正如您所知,所有的
getStuffByToken(…)
调用都是在
主线程上执行的

接下来,您的测试方法没有被调用的原因是
TestScheduler
需要调用
TestScheduler.advanceTimeBy(…)
来模拟导致Rx管道处理的时间流逝。由于您的方法是一种阻塞方法,因此使用
TestScheduler
进行测试并不方便

根据以上两条信息,我建议您按照以下思路做一些事情:

public Single<List<String>> extractStuff( Scheduler scheduler, List<Integer> tokens )
{
    return Observable.fromIterable( tokens )
        .flatMap( token -> Observable.just( token )
                .subscribeOn( scheduler )
                .map( this::getStuffByToken )
                .flatMap( Observable::fromIterable ))
        .toList();
}

我同意您的看法,将
TestScheduler
advanceTimeBy
一起使用是一个更好的解决方案,但我现在必须处理一些遗留代码。第一个解决方案(使用调度程序.computation()
)成功了。有没有任何官方文档可以让我找到这些信息?@DavidL,官方文档分为几个站点。对于一般反应流概念:。对于特定于Java的:在.NET的“Rx简介”一书中介绍了单元测试:
@Test
public void testExtractStuff()
{
    List<Integer> tokens = Arrays.asList( 1, 2, 3, 4, 5 );
    List<String> result = extractStuff( Schedulers.computation(), tokens );
    System.out.println( result );
}
[1, main, 3, main, 4, main, 5, main, 2, main]
public Single<List<String>> extractStuff( Scheduler scheduler, List<Integer> tokens )
{
    return Observable.fromIterable( tokens )
        .flatMap( token -> Observable.just( token )
                .subscribeOn( scheduler )
                .map( this::getStuffByToken )
                .flatMap( Observable::fromIterable ))
        .toList();
}
@Test
public void testExtractStuff()
{
    TestScheduler scheduler = new TestScheduler();
    List<Integer> tokens = Arrays.asList( 1, 2, 3, 4, 5 );
    TestObserver<List<String>> test = extractStuff( scheduler, tokens ).test();

    scheduler.advanceTimeBy( 1, TimeUnit.SECONDS );
    test.assertValueCount( 1 );
    test.assertValue( list -> list.size() == 10 );
    test.assertComplete();
}