@Test
  public void start_errorThenRestarted() throws Exception {
    startAndVerify();

    replicator.stop();
    Assert.assertEquals(Replicator.State.STOPPING, replicator.getState());

    ErrorInfo err = new ErrorInfo(new RuntimeException("Mocked error"));
    ReplicationStrategyErrored rse = new ReplicationStrategyErrored(mockStrategy, err);
    ReplicationErrored re = new ReplicationErrored(replicator, err);
    replicator.error(rse);
    Assert.assertEquals(Replicator.State.ERROR, replicator.getState());
    verify(mockListener).error(re);
    verify(mockListener, never()).complete(any(ReplicationCompleted.class));

    doAnswer(
            new Answer() {
              @Override
              public Object answer(InvocationOnMock invocation) throws Throwable {
                Thread.sleep(1000); // sleep for a second, will give enough time to check state
                return null;
              }
            })
        .when(mockStrategy)
        .run();
    replicator.start();
    Assert.assertEquals(Replicator.State.STARTED, replicator.getState());
    Assert.assertTrue(replicator.strategyThread().isAlive());
    replicator.await();
    Assert.assertFalse(replicator.strategyThread().isAlive());
    verify(mockStrategy, times(2)).run();
  }
  @Test
  public void testListenerErrorCanRestartReplication()
      throws URISyntaxException, InterruptedException {
    Listener listener = new Listener();

    URI uri = new URI("http://127.0.0.1:5984/db1");
    DatastoreExtended mockDatastore = mock(DatastoreExtended.class);
    ReplicationStrategy mockStrategy = mock(ReplicationStrategy.class);
    when(mockStrategy.isReplicationTerminated()).thenReturn(true);
    when(mockStrategy.getEventBus()).thenReturn(new EventBus());

    PullReplication pull = createPullReplication(uri, mockDatastore);
    TestReplicator replicator = new TestReplicator(pull, mockStrategy);
    replicator.getEventBus().register(listener);
    replicator.start();

    // Waits for callbacks to be run
    replicator.error(
        new ReplicationStrategyErrored(
            mockStrategy, new ErrorInfo(new RuntimeException("Mocked error"))));

    Assert.assertTrue(listener.run);
    Assert.assertFalse(listener.errorThrown);

    // Don't leave threads about the place
    replicator.complete(new ReplicationStrategyCompleted(mockStrategy));
  }
  @Test
  public void error_woListener_nothing() {
    // don't subscribe to the eventbus
    replicator.start();
    replicator.error(
        new ReplicationStrategyErrored(
            mockStrategy, new ErrorInfo(new RuntimeException("Mocked error"))));

    verify(mockListener, never()).complete(any(ReplicationCompleted.class));
    verify(mockListener, never()).error(any(ReplicationErrored.class));
  }
  @Test
  public void startAndThenError_errorState() throws Exception {
    startAndVerify();

    ErrorInfo err = new ErrorInfo(new RuntimeException("Mocked error"));
    ReplicationStrategyErrored rse = new ReplicationStrategyErrored(mockStrategy, err);
    ReplicationErrored re = new ReplicationErrored(replicator, err);

    replicator.error(rse);

    verify(mockListener).error(re);
    verify(mockListener, never()).complete(any(ReplicationCompleted.class));

    Assert.assertEquals(Replicator.State.ERROR, replicator.getState());
    Assert.assertFalse(replicator.strategyThread().isAlive());
  }