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();
}