### Question:
BatchImporter { public SafeFuture<BatchImportResult> importBatch(final Batch batch) { final List<SignedBeaconBlock> blocks = new ArrayList<>(batch.getBlocks()); checkState(!blocks.isEmpty(), "Batch has no blocks to import"); return asyncRunner.runAsync( () -> { SafeFuture<BlockImportResult> importResult = blockImporter.importBlock(blocks.get(0)); for (int i = 1; i < blocks.size(); i++) { final SignedBeaconBlock block = blocks.get(i); importResult = importResult.thenCompose( previousResult -> { if (previousResult.isSuccessful()) { return blockImporter.importBlock(block); } else { return SafeFuture.completedFuture(previousResult); } }); } return importResult.thenApply( lastBlockImportResult -> { if (lastBlockImportResult.isSuccessful()) { return BatchImportResult.IMPORTED_ALL_BLOCKS; } LOG.debug( "Failed to import batch {}: {}", batch, lastBlockImportResult.getFailureReason(), lastBlockImportResult.getFailureCause().orElse(null)); return BatchImportResult.IMPORT_FAILED; }); }); } BatchImporter(final BlockImporter blockImporter, final AsyncRunner asyncRunner); SafeFuture<BatchImportResult> importBatch(final Batch batch);  }### Answer:
@Test void shouldImportBlocksInOrder() { final SignedBeaconBlock block1 = dataStructureUtil.randomSignedBeaconBlock(1); final SignedBeaconBlock block2 = dataStructureUtil.randomSignedBeaconBlock(2); final SignedBeaconBlock block3 = dataStructureUtil.randomSignedBeaconBlock(3); final SafeFuture<BlockImportResult> importResult1 = new SafeFuture<>(); final SafeFuture<BlockImportResult> importResult2 = new SafeFuture<>(); final SafeFuture<BlockImportResult> importResult3 = new SafeFuture<>(); final List<SignedBeaconBlock> blocks = new ArrayList<>(List.of(block1, block2, block3)); when(batch.getBlocks()).thenReturn(blocks); when(blockImporter.importBlock(block1)).thenReturn(importResult1); when(blockImporter.importBlock(block2)).thenReturn(importResult2); when(blockImporter.importBlock(block3)).thenReturn(importResult3); final SafeFuture<BatchImportResult> result = importer.importBatch(batch); verifyNoInteractions(blockImporter); verify(batch).getBlocks(); blocks.clear(); asyncRunner.executeQueuedActions(); blockImportedSuccessfully(block1, importResult1); assertThat(result).isNotDone(); blockImportedSuccessfully(block2, importResult2); assertThat(result).isNotDone(); blockImportedSuccessfully(block3, importResult3); assertThat(result).isCompletedWithValue(BatchImportResult.IMPORTED_ALL_BLOCKS); verifyNoMoreInteractions(batch); }
@Test void shouldStopImportingAfterFailure() { final SignedBeaconBlock block1 = dataStructureUtil.randomSignedBeaconBlock(1); final SignedBeaconBlock block2 = dataStructureUtil.randomSignedBeaconBlock(2); final SignedBeaconBlock block3 = dataStructureUtil.randomSignedBeaconBlock(3); final SafeFuture<BlockImportResult> importResult1 = new SafeFuture<>(); final SafeFuture<BlockImportResult> importResult2 = new SafeFuture<>(); final SafeFuture<BlockImportResult> importResult3 = new SafeFuture<>(); when(batch.getBlocks()).thenReturn(List.of(block1, block2, block3)); when(blockImporter.importBlock(block1)).thenReturn(importResult1); when(blockImporter.importBlock(block2)).thenReturn(importResult2); when(blockImporter.importBlock(block3)).thenReturn(importResult3); final SafeFuture<BatchImportResult> result = importer.importBatch(batch); verifyNoInteractions(blockImporter); asyncRunner.executeQueuedActions(); blockImportedSuccessfully(block1, importResult1); assertThat(result).isNotDone(); ignoreFuture(verify(blockImporter).importBlock(block2)); verifyNoMoreInteractions(blockImporter); importResult2.complete( BlockImportResult.failedStateTransition(new Exception("Naughty block!"))); assertThat(result).isCompletedWithValue(BatchImportResult.IMPORT_FAILED); verifyNoMoreInteractions(blockImporter); }