Fetcher { public boolean fetchData() { Date snapshotDate = from(now()); logger.info("Starting fetching data. Snapshot date: {} {}, IP and MAC Address: {}.", snapshotDate, snapshotDate.getTime(), getIpAndMacAddress()); List<Future<Snapshot>> futures = new ArrayList<>(); try { for (String organizationName : organizations) { futures.add(snapshotProvider.takeSnapshot(organizationName, snapshotDate)); logger.info("Enqueued task TakeSnapshotTask for organization '{}'.", organizationName); } } catch (IOException e) { logger.error("Unable to fetch data from GitHub API. Missing GitHub API credentials?.", e); throw new CrawlerRetryException(e); } logger.info("Submitted {} TakeSnapshotTasks.", futures.size()); for (Future<Snapshot> future : futures) { try { Snapshot snapshot = future.get(); statisticsRepository.save(snapshot.getStatistics()); projectRepository.save(snapshot.getProjects()); contributorRepository.save(snapshot.getContributors()); logger.info("Successfully saved data for organization '{}'.", snapshot.getStatistics() .getOrganizationName()); } catch (InterruptedException | ExecutionException e) { logger.error("Error occurred while processing organization.", e); throw new CrawlerRetryException(e); } } logger.info("Finished fetching data."); return true; } @Autowired  Fetcher(ProjectRepository projectRepository,
                   StatisticsRepository statisticsRepository,
                   ContributorRepository contributorRepository,
                   SnapshotProvider snapshotProvider,
                   @Value("#{'${organization.list}'.split(',')}") String[] organizations); boolean fetchData();  }
@SuppressWarnings("unchecked") @Test public void shouldRetryThreeTimes() throws Exception { when(fetcher.fetchData()) .thenThrow(CrawlerRetryException.class) .thenThrow(CrawlerRetryException.class) .thenReturn(true); retryableFetcher.tryFetchData(); verify(fetcher, times(3)).fetchData(); }