@Test
  public void startAndRescheduleTwoJobs_sameProcess_stopsOnReschedule() throws Exception {
    CountDownLatch startLatch = new CountDownLatch(2);
    // Does not need to be concurrent because access is guarded by the startLatch.
    Set<String> startedJobs = new HashSet<>();
    CountDownLatch stopLatch = new CountDownLatch(2);
    // Does not need to be concurrent because access is guarded by the stopLatch.
    Set<String> stoppedJobs = new HashSet<>();
    TestJobService.setProxy(
        new TestJobService.JobServiceProxy() {
          @Override
          public boolean onStartJob(JobService jobService, JobParameters job) {
            startedJobs.add(job.getTag());
            startLatch.countDown();
            return true;
          }

          @Override
          public boolean onStopJob(JobService jobService, JobParameters job) {
            stoppedJobs.add(job.getTag());
            stopLatch.countDown();
            return false;
          }
        });

    Bundle extras = new Bundle();
    extras.putBoolean("extras", true);

    dispatcher.mustSchedule(
        dispatcher
            .newJobBuilder()
            .setService(TestJobService.class)
            .setTrigger(Trigger.NOW)
            .setTag(FIRST_JOB)
            .setExtras(extras)
            .build());

    dispatcher.mustSchedule(
        dispatcher
            .newJobBuilder()
            .setService(TestJobService.class)
            .setTrigger(Trigger.NOW)
            .setTag(SECOND_JOB)
            .setExtras(extras)
            .build());
    assertTrue(startLatch.await(120, TimeUnit.SECONDS));
    assertEquals(2, startedJobs.size());
    assertTrue(startedJobs.contains(FIRST_JOB));
    assertTrue(startedJobs.contains(SECOND_JOB));
    assertTrue(stoppedJobs.isEmpty());

    // reschedule
    dispatcher.mustSchedule(
        dispatcher
            .newJobBuilder()
            .setService(TestJobService.class)
            .setTrigger(Trigger.NOW)
            .setTag(FIRST_JOB)
            .setExtras(extras)
            .build());

    dispatcher.mustSchedule(
        dispatcher
            .newJobBuilder()
            .setService(TestJobService.class)
            .setTrigger(Trigger.NOW)
            .setTag(SECOND_JOB)
            .setExtras(extras)
            .build());

    assertTrue(stopLatch.await(120, TimeUnit.SECONDS));
    assertEquals(2, stoppedJobs.size());
    assertTrue(stoppedJobs.contains(FIRST_JOB));
    assertTrue(stoppedJobs.contains(SECOND_JOB));
  }
Basic end to end test for the JobDispatcher. Requires Google Play services be installed and
available.
jobdispatcher/src/androidTest/java/com/firebase/jobdispatcher/EndToEndAndroidTest.java