### Question:
FastDownloaderFactory { public static Optional<FastSyncDownloader> create( final SynchronizerConfiguration syncConfig, final Path dataDirectory, final ProtocolSchedule protocolSchedule, final ProtocolContext protocolContext, final MetricsSystem metricsSystem, final EthContext ethContext, final WorldStateStorage worldStateStorage, final SyncState syncState, final Clock clock) { final Path fastSyncDataDirectory = dataDirectory.resolve(FAST_SYNC_FOLDER); final FastSyncStateStorage fastSyncStateStorage = new FastSyncStateStorage(fastSyncDataDirectory); if (syncConfig.getSyncMode() != SyncMode.FAST) { if (fastSyncStateStorage.isFastSyncInProgress()) { throw new IllegalStateException( "Unable to change the sync mode when fast sync is incomplete, please restart with fast sync mode"); } else { return Optional.empty(); } } ensureDirectoryExists(fastSyncDataDirectory.toFile()); final FastSyncState fastSyncState = fastSyncStateStorage.loadState(ScheduleBasedBlockHeaderFunctions.create(protocolSchedule)); if (fastSyncState.getPivotBlockHeader().isEmpty() && protocolContext.getBlockchain().getChainHeadBlockNumber() != BlockHeader.GENESIS_BLOCK_NUMBER) { LOG.info( "Fast sync was requested, but cannot be enabled because the local blockchain is not empty."); return Optional.empty(); } final CachingTaskCollection<NodeDataRequest> taskCollection = createWorldStateDownloaderTaskCollection( getStateQueueDirectory(dataDirectory), metricsSystem, syncConfig.getWorldStateTaskCacheSize()); final WorldStateDownloader worldStateDownloader = new WorldStateDownloader( ethContext, worldStateStorage, taskCollection, syncConfig.getWorldStateHashCountPerRequest(), syncConfig.getWorldStateRequestParallelism(), syncConfig.getWorldStateMaxRequestsWithoutProgress(), syncConfig.getWorldStateMinMillisBeforeStalling(), clock, metricsSystem); final FastSyncDownloader fastSyncDownloader = new FastSyncDownloader( new FastSyncActions( syncConfig, protocolSchedule, protocolContext, ethContext, syncState, metricsSystem), worldStateDownloader, fastSyncStateStorage, taskCollection, fastSyncDataDirectory, fastSyncState); syncState.setWorldStateDownloadStatus(worldStateDownloader); return Optional.of(fastSyncDownloader); }  static Optional<FastSyncDownloader> create(
      final SynchronizerConfiguration syncConfig,
      final Path dataDirectory,
      final ProtocolSchedule protocolSchedule,
      final ProtocolContext protocolContext,
      final MetricsSystem metricsSystem,
      final EthContext ethContext,
      final WorldStateStorage worldStateStorage,
      final SyncState syncState,
      final Clock clock);  }### Answer:
@SuppressWarnings("unchecked") @Test(expected = IllegalStateException.class) public void shouldThrowIfSyncModeChangedWhileFastSyncIncomplete() throws NoSuchFieldException { initDataDirectory(true); when(syncConfig.getSyncMode()).thenReturn(SyncMode.FULL); FastDownloaderFactory.create( syncConfig, dataDirectory, protocolSchedule, protocolContext, metricsSystem, ethContext, worldStateStorage, syncState, clock); }
@SuppressWarnings({"unchecked", "rawtypes"}) @Test public void shouldNotThrowIfSyncModeChangedWhileFastSyncComplete() throws NoSuchFieldException { initDataDirectory(false); when(syncConfig.getSyncMode()).thenReturn(SyncMode.FULL); final Optional result = FastDownloaderFactory.create( syncConfig, dataDirectory, protocolSchedule, protocolContext, metricsSystem, ethContext, worldStateStorage, syncState, clock); assertThat(result).isEmpty(); }
@SuppressWarnings("unchecked") @Test public void shouldNotThrowWhenFastSyncModeRequested() throws NoSuchFieldException { initDataDirectory(false); final MutableBlockchain mutableBlockchain = mock(MutableBlockchain.class); when(mutableBlockchain.getChainHeadBlockNumber()).thenReturn(0L); when(protocolContext.getBlockchain()).thenReturn(mutableBlockchain); when(syncConfig.getSyncMode()).thenReturn(SyncMode.FAST); FastDownloaderFactory.create( syncConfig, dataDirectory, protocolSchedule, protocolContext, metricsSystem, ethContext, worldStateStorage, syncState, clock); verify(mutableBlockchain).getChainHeadBlockNumber(); }