### Question:
ShardService { public void recoverSharding() { ShardRecovery recovery = shardRecoveryDao.getLatestShardRecovery(); boolean isShardingOff = propertiesHolder.getBooleanProperty("apl.noshardcreate", false); boolean shardingEnabled = blockchainConfig.getCurrentConfig().isShardingEnabled(); boolean shardingEnabledRecoveryExists = shardingEnabled && recovery != null; boolean doRecovery = !isShardingOff && shardingEnabledRecoveryExists && recovery.getState() != MigrateState.COMPLETED; boolean deleteRecovery = isShardingOff && shardingEnabledRecoveryExists && recovery.getState() == MigrateState.INIT; log.debug("do recovery = '{}' parts : (!{} && {} && {} && {})", doRecovery, isShardingOff, shardingEnabled, recovery != null, recovery != null ? recovery.getState() != MigrateState.COMPLETED : "false" ); if (doRecovery) { isSharding = true; long start = System.currentTimeMillis(); try { aplAppStatus.durableTaskStart("sharding", "Blockchain db sharding process takes some time, pls be patient...", true); Shard lastShard = shardDao.getLastShard(); shardMigrationExecutor.prepare(); shardMigrationExecutor.createAllCommands(lastShard.getShardHeight(), lastShard.getShardId(), recovery.getState()); shardMigrationExecutor.executeAllOperations(); log.info("Finished sharding by recovery, height='{}' in {} ms", recovery.getHeight(), System.currentTimeMillis() - start); aplAppStatus.durableTaskFinished("sharding", false, "Shard process finished"); } finally { isSharding = false; } } else if (deleteRecovery) { deleteRecovery(recovery); } } @Inject  ShardService(ShardDao shardDao, BlockchainProcessor blockchainProcessor, Blockchain blockchain,
                        DirProvider dirProvider, Zip zip, DatabaseManager databaseManager,
                        BlockchainConfig blockchainConfig, ShardRecoveryDao shardRecoveryDao,
                        ShardMigrationExecutor shardMigrationExecutor, AplAppStatus aplAppStatus,
                        PropertiesHolder propertiesHolder, Event<TrimConfig> trimEvent, GlobalSync globalSync,
                        TrimService trimService, Event<DbHotSwapConfig> dbEvent); List<Shard> getAllCompletedShards(); List<Shard> getAllCompletedOrArchivedShards(); List<Shard> getAllShards(); boolean isSharding(); void setSharding(boolean sharding); boolean reset(long shardId); void recoverSharding(); MigrateState performSharding(int minRollbackHeight, long shardId, MigrateState initialState); CompletableFuture<MigrateState> tryCreateShardAsync(int lastTrimBlockHeight, int blockchainHeight); @Transactional void saveShardRecoveryAndShard(long nextShardId, int lastTrimBlockHeight, int blockchainHeight); Shard getLastShard(); List<Shard> getShardsByBlockHeightRange(int heightFrom, int heightTo); final static long LOWER_SHARDING_MEMORY_LIMIT; }### Answer:
@Test void testRecoverWhenShardingWasNotEnabled() { doReturn(mock(HeightConfig.class)).when(blockchainConfig).getCurrentConfig(); shardService.recoverSharding(); verifyZeroInteractions(shardMigrationExecutor); }
@Test void testRecoverWhenRecoveryIsNull() { HeightConfig config = mock(HeightConfig.class); doReturn(config).when(blockchainConfig).getCurrentConfig(); doReturn(true).when(config).isShardingEnabled(); shardService.recoverSharding(); verifyZeroInteractions(shardMigrationExecutor); }
@Test void testRecoverWhenRecoveryIsCompleted() { HeightConfig config = mock(HeightConfig.class); doReturn(config).when(blockchainConfig).getCurrentConfig(); doReturn(true).when(config).isShardingEnabled(); doReturn(new ShardRecovery(MigrateState.COMPLETED)).when(shardRecoveryDao).getLatestShardRecovery(); shardService.recoverSharding(); verifyZeroInteractions(shardMigrationExecutor); }