我无法测试我的RxJava代码,因为它似乎总是在测试中运行而不等待调用subscribe()时应该执行的执行。
这是要测试的存储库:
public class Repository<T extends Entity> {
private final DataSource<T> remoteDataSource;
private final DataSource<T> localDataSource;
public Repository(DataSource<T> remoteDataSource, DataSource<T> localDataSource) {
this.remoteDataSource = remoteDataSource;
this.localDataSource = localDataSource;
}
public Observable<Boolean> save(T entity) {
return localDataSource
.save(entity)
.flatMap(success -> {
if (success) {
return remoteDataSource.save(entity);
}
return Observable.just(Boolean.FALSE);
})
.doOnNext(success -> {
if (success) {
if (cache == null) {
cache = new LinkedHashMap<>();
}
cache.put(entity.getId(), entity);
}
});
}
}
这是DataSource接口:
public interface DataSource<T extends Entity> {
<T> Observable<T> get();
Observable<Boolean> save(T entity);
Observable<Boolean> clear();
Observable<Boolean> remove(T entity);
}
这是单元测试,包括一个MockDataSource,它应该用不同的执行时序模拟数据访问:
public class RepositoryTest {
@Test
public void testRepository() {
MockSource remoteSource = new MockSource("RemoteSource", 1000L);
MockSource localSource = new MockSource("LocalSource", 200L);
Repository<Poi> poiRepository = new Repository<>(remoteSource, localSource);
Poi poi1 = newMockPoi();
Observable<Boolean> obs = poiRepository.save(poi1);
TestSubscriber<Boolean> testSubscriber = new TestSubscriber<>();
obs.subscribe(testSubscriber);
testSubscriber.assertNoErrors();
testSubscriber.assertReceivedOnNext(Arrays.asList(true));
}
private Poi newMockPoi() {
Poi poi = new Poi();
poi.name = RandomStringUtils.randomAlphabetic(12);
poi.description = RandomStringUtils.randomAlphabetic(255);
poi.latitude = new Random().nextDouble();
poi.longitude = new Random().nextDouble();
return poi;
}
private class Poi extends Entity {
String name;
String description;
Double latitude;
Double longitude;
}
private class MockSource implements DataSource<Poi> {
private String name;
private final long delayInMilliseconds;
private Map<Long, Poi> pois = new LinkedHashMap<>();
private MockSource(String name, long delayInMilliseconds) {
this.delayInMilliseconds = delayInMilliseconds;
this.name = name;
}
@Override
public Observable<List<Poi>> get() {
return Observable
.zip(
Observable
.just(pois)
.map(Map::entrySet)
.flatMapIterable(entries -> entries)
.map(Map.Entry::getValue)
.toList(),
Observable
.interval(delayInMilliseconds, TimeUnit.MILLISECONDS), (obs, timer) -> obs)
.doOnNext(pois -> System.out.println("Soure " + name + " emitted entity"));
}
@Override
public Observable<Boolean> save(Poi entity) {
return Observable
.zip(
Observable.just(true).asObservable(),
Observable.interval(delayInMilliseconds, TimeUnit.MILLISECONDS), (obs, timer) -> obs)
.doOnNext(value -> pois.put(entity.getId(), entity))
.doOnNext(pois -> System.out.println("Soure " + name + " saved entity"));
}
@Override
public Observable<Boolean> clear() {
return Observable
.zip(
Observable.just(true).asObservable(),
Observable.interval(delayInMilliseconds, TimeUnit.MILLISECONDS), (obs, timer) -> obs)
.doOnNext(value -> pois.clear())
.doOnNext(pois -> System.out.println("Soure " + name + " cleared all entities"));
}
@Override
public Observable<Boolean> remove(Poi entity) {
return Observable
.zip(
Observable.just(true).asObservable(),
Observable.interval(delayInMilliseconds, TimeUnit.MILLISECONDS), (obs, timer) -> obs)
.doOnNext(value -> pois.remove(entity))
.doOnNext(pois -> System.out.println("Soure " + name + " removed entity"));
}
}
}
这是输出:
java.lang.AssertionError: Number of items does not match. Provided: 1
Actual: 0.
Provided values: [true]
Actual values: []
(0 completions)
at rx.observers.TestSubscriber.assertionError(TestSubscriber.java:667)
at rx.observers.TestSubscriber.assertReceivedOnNext(TestSubscriber.java:320)
at nl.itc.geofara.app.data.source.RepositoryTest.testRepository(RepositoryTest.java:37)
另外,在存储库的save方法中设置断点并在调试模式下运行会显示例如永远不会调用.flatMap(success - &gt; ...)。
答案 0 :(得分:2)
您在可观察执行和JUnit线程之间遇到 竞争条件 ,因为您在模拟源中使用的Observable.interval
引入了implicit subscription on computation scheduler }:
调度程序: 默认情况下,interval在计算Scheduler上运行。
此外,请参阅this answer,&#34;疑难解答&#34;,&#34;竞争条件&#34;中的更多解释。