从集合中创建元素流

时间:2017-09-12 23:02:40

标签: java mongodb unit-testing junit5 mongodb-asyc-driver

我正在使用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中有百万条记录,并且正在运行与它们类似的集成测试用例。将所有这些加载到内存中是不可行的,因此我正在尝试流式解决方案。

1 个答案:

答案 0 :(得分:0)

我认为我并不完全理解您的用例,但鉴于您的问题标有javamongo-asyc-driver,这个要求肯定是可以实现的:

  

从集合中创建一个元素流,将其传递给测试...使这个工作无缝地无阻塞

以下代码:

  • 使用MongoDB RxJava驱动程序查询集合
  • 从该集合中创建一个Rx 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(); 
    

注意:

  • 这需要使用MongoDB RxJava driver(即com.mongodb.rx.client命名空间中的类...... org.mongodb::mongodb-driver-rx Maven工件)
  • 在您的问题中,您正在调用collection.find().batchSize(),这清楚地表明您当前 正在使用Rx驱动程序(因为batchSize不能是Rx友好概念:)
  • 使用MongoDB RxJava驱动程序的v1.4.0和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耗尽时,锁存器将递减,代码将完成。