我正在使用Junit 5动态测试。 我的目的是从集合中创建一个元素流,将其传递给JUnit5进行测试。 但是使用此代码,我只能运行1000条记录。如何使这项工作无缝地无阻塞。
MongoCollection<Document> collection = mydatabase.getCollection("mycoll");
final List<Document> cache = Collections.synchronizedList(new ArrayList<Document>());
FindIterable<Document> f = collection.find().batchSize(1000);
f.batchCursor(new SingleResultCallback<AsyncBatchCursor<Document>>() {
@Override
public void onResult(AsyncBatchCursor<Document> t, Throwable thrwbl) {
t.next(new SingleResultCallback<List<Document>>() {
@Override
public void onResult(List<Document> t, Throwable thrwbl) {
if (thrwbl != null) {
th.set(thrwbl);
}
cache.addAll(t);
latch.countDown();;
}
});
}
});
latch.await();
return cache.stream().map(batch->process(batch));
更新代码
@ParameterizedTest
@MethodSource("setUp")
void cacheTest(MyClazz myclass) throws Exception {
assertTrue(doTest(myclass));
}
public static MongoClient getMongoClient() {
// get client here
}
private static Stream<MyClazz> setUp() throws Exception {
MongoDatabase mydatabase = getMongoClient().getDatabase("test");
List<Throwable> failures = new ArrayList<>();
CountDownLatch latch = new CountDownLatch(1);
List<MyClazz> list = Collections.synchronizedList(new ArrayList<>());
mydatabase.getCollection("testcollection").find()
.toObservable().subscribe(
document -> {
list.add(process(document));
},
throwable -> {
failures.add(throwable);
},
() -> {
latch.countDown();
});
latch.await();
return list.stream();
}
public boolean doTest(MyClazz myclass) {
// processing goes here
}
public MyClazz process(Document doc) {
// doc gets converted to MyClazz
return MyClazz;
}
即使是现在,我看到所有数据都已加载,然后进行单元测试。 我认为这是因为latch.await()。但是,如果我删除它,则可能没有运行测试用例,因为db可能正在加载集合。
我的用例是:我在mongo中有百万条记录,并且正在运行与它们类似的集成测试用例。将所有这些加载到内存中是不可行的,因此我正在尝试流式解决方案。
答案 0 :(得分:0)
我认为我并不完全理解您的用例,但鉴于您的问题标有java
和mongo-asyc-driver
,这个要求肯定是可以实现的:
从集合中创建一个元素流,将其传递给测试...使这个工作无缝地无阻塞
以下代码:
Observable
Observable
标记完成
CountDownLatch latch = new CountDownLatch(1);
List<Throwable> failures = new ArrayList<>();
collection.find()
.toObservable().subscribe(
// on next, this is invoked for each document returned by your find call
document -> {
// presumably you'll want to do something here to meet this requirement: "pass it on to test in JUnit5"
System.out.println(document);
},
/// on error
throwable -> {
failures.add(throwable);
},
// on completion
() -> {
latch.countDown();
});
// await the completion event
latch.await();
注意:
com.mongodb.rx.client
命名空间中的类...... org.mongodb::mongodb-driver-rx
Maven工件)collection.find().batchSize()
,这清楚地表明您当前 正在使用Rx驱动程序(因为batchSize
不能是Rx友好概念:)io.reactive::rxjava
的v1.1.10 更新1 :根据您的问题的更改(在我的原始答案之后),您已经询问:“我看到所有数据都已加载,之后单元测试发生我认为这是因为latch.await()“?我认为你正在弹出[从可观察流中获取一个列表而仅在observable耗尽之后你是否开始调用doTest()
。这种方法涉及(1)来自MongoDB的流式传输结果; (2)将这些结果存储在内存中; (3)为每个存储的结果运行doTest()
。如果您真的想要全程流式传输,那么您应该从您的observable订阅中调用doTest()
。例如:
mydatabase.getCollection("testcollection").find()
.toObservable().subscribe(
document -> {
doTest(process(document));
},
throwable -> {
failures.add(throwable);
},
() -> {
latch.countDown();
});
latch.await();
上面的代码将调用doTest()
,因为它从MongoDB接收每个文档,当整个observable耗尽时,锁存器将递减,代码将完成。