### Question:
Puller { void pull(String elementId, Queue<Item> queue, CompletableFuture resultFuture, int count) { dbClient.getNextBatchAfterId(elementId, count) .thenAccept(items -> { for (Item item : items) { if (isValid(item)) { queue.offer(item); if (queue.size() == count) { resultFuture.complete(queue); return; } } } pull(items.get(items.size() - 1) .getId(), queue, resultFuture, count); }); }  CompletionStage<Queue<Item>> list(int count);  }### Answer:
@Test public void pullTest() throws InterruptedException { CountDownLatch l = new CountDownLatch(1); Puller puller = new Puller(); CompletionStage<Queue<Item>> list = puller.list(10); list.thenAccept(q -> { MatcherAssert.assertThat(q, Matchers.allOf( Matchers.hasSize(10), Matchers.contains( Matchers.hasProperty("id", Matchers.equalTo("2")), Matchers.hasProperty("id", Matchers.equalTo("4")), Matchers.hasProperty("id", Matchers.equalTo("6")), Matchers.hasProperty("id", Matchers.equalTo("8")), Matchers.hasProperty("id", Matchers.equalTo("10")), Matchers.hasProperty("id", Matchers.equalTo("12")), Matchers.hasProperty("id", Matchers.equalTo("14")), Matchers.hasProperty("id", Matchers.equalTo("16")), Matchers.hasProperty("id", Matchers.equalTo("18")), Matchers.hasProperty("id", Matchers.equalTo("20")) ) )); l.countDown(); }) .exceptionally(t -> { l.countDown(); throw new RuntimeException(t); }); l.await(); }