protected Pair<Map<DataNodeId, List<RemoteReplicaInfo>>, ReplicaThread> getRemoteReplicasAndReplicaThread(
      boolean createBackupCheckerThread, int batchSize, ClusterMap clusterMap, MockHost localHost,
      StoreKeyConverter storeKeyConverter, Transformer transformer, StoreEventListener listener,
      ReplicaSyncUpManager replicaSyncUpManager, MockHost... remoteHosts) throws ReflectiveOperationException {
    ReplicationMetrics replicationMetrics =
        new ReplicationMetrics(new MetricRegistry(), clusterMap.getReplicaIds(localHost.dataNodeId));
    StoreKeyFactory storeKeyFactory = Utils.getObj("com.github.ambry.commons.BlobIdFactory", clusterMap);
    Map<DataNodeId, MockHost> hosts = new HashMap<>();
    Map<DataNodeId, List<RemoteReplicaInfo>> replicasToReplicate = new HashMap<>();
    for (MockHost remoteHost : remoteHosts) {
      replicationMetrics.populateSingleColoMetrics(remoteHost.dataNodeId.getDatacenterName());
      List<RemoteReplicaInfo> remoteReplicaInfoList = localHost.getRemoteReplicaInfos(remoteHost, listener);
      replicasToReplicate.put(remoteHost.dataNodeId, remoteReplicaInfoList);
      hosts.put(remoteHost.dataNodeId, remoteHost);
    }
    FindTokenHelper findTokenHelper = new MockFindTokenHelper(storeKeyFactory, replicationConfig);
    MockNetworkClient networkClient = new MockNetworkClient(hosts, clusterMap, batchSize, findTokenHelper);
    ReplicaThread replicaThread = null;
    if (createBackupCheckerThread) {
      replicaThread =
          new BackupCheckerThread("threadtest", findTokenHelper, clusterMap, new AtomicInteger(0), localHost.dataNodeId,
              networkClient, replicationConfig, replicationMetrics, null, storeKeyConverter, storeKeyFactory, transformer,
              clusterMap.getMetricRegistry(), false, localHost.dataNodeId.getDatacenterName(),
              new ResponseHandler(clusterMap), time, replicaSyncUpManager, null, null);
    } else {
      replicaThread =
          new ReplicaThread("threadtest", findTokenHelper, clusterMap, new AtomicInteger(0), localHost.dataNodeId,
              networkClient, replicationConfig, replicationMetrics, null, storeKeyConverter, transformer,
              clusterMap.getMetricRegistry(), false, localHost.dataNodeId.getDatacenterName(),
              new ResponseHandler(clusterMap), time, replicaSyncUpManager, null, null);
    }
    for (MockHost remoteHost : remoteHosts) {
      for (RemoteReplicaInfo remoteReplicaInfo : replicasToReplicate.get(remoteHost.dataNodeId)) {
        replicaThread.addRemoteReplicaInfo(remoteReplicaInfo);
      }
    }
    for (PartitionId partitionId : clusterMap.getAllPartitionIds(null)) {
      replicationMetrics.addLagMetricForPartition(partitionId, true);
    }

    return new Pair<>(replicasToReplicate, replicaThread);
  }
Creates and gets the remote replicas that the local host will deal with and the {@link ReplicaThread} to perform
replication with.
@param createBackupCheckerThread true to create a {@link BackupCheckerThread}, other, create {@link ReplicaThread}.
@param batchSize the number of messages to be returned in each iteration of replication
@param clusterMap the {@link ClusterMap} to use
@param localHost the local {@link MockHost} (the one running the replica thread)
@param storeKeyConverter the {@link StoreKeyConverter} to be used in {@link ReplicaThread}
@param transformer the {@link Transformer} to be used in {@link ReplicaThread}
@param listener the {@link StoreEventListener} to use.
@param replicaSyncUpManager the {@link ReplicaSyncUpManager} to help create replica thread
@param remoteHosts the list of remote {@link MockHost} (the target of replication)
@return a pair whose first element is the set of remote replicas and the second element is the {@link ReplicaThread}
ambry-replication/src/test/java/com/github/ambry/replication/ReplicationTestHelper.java