title: How to write a UT for a Runnable java class which has an infinite loop in run()?
body: <p>I have a java class like below. Its job is monitor a file, if that file's size does not change at certain interval, it will raise alert.</p>
  
  <p>I'd like to write two UTs for it. </p>
  
  <p>1.Simulates the file size keeps unchanges. </p>
  
  <p>2.Simulate file size keeps changes for a while. After that file size will change.</p>
  
  <p>The UT will verify alerter.alert() or alerter.harmless() is really invoked when condition is or isn't met. I mocked Alerter and passed it to Task's constructor. But how to control the timing for run()? I know timing for multi-thread cannot be controlled accurately. I just would like to know what is the best practice to write ut for this kind of class. If possible, please write a test sample. </p>
  
  <p>You can regard that "<strong>some condition</strong>" as checking if a specified file's size changes at a certain interval. If not changed, some condition will be true. </p>
  
  <pre><code>class Task implements Runnable{
      Alerter alerter;
      boolean stop=false;
      public Task(Alerter alerter){
          this.alerter=alerter;
      }
      public void run() {
          while (!stop){
  
              if (some condition){
                  alerter.alert();
              } else{
                  alerter.harmless();
              } 
  
              Thread.sleep(5000);
  
          }
      }
      public synchronized void stop(){
          stop=true;
      }
  
  }
  </code></pre>
  
  <p>I'm thinking of writing uts like below. But I don't think it is good enough.</p>
  
  <pre><code>@Test
  public void testRunWithFeed() {
      Alerter mockAlerter=mock(Alerter.class);
      Task task=new Task(mockAlerter);
      Thread thread =new Thread(task);
      thread.start();
      try {
          Thread.sleep(1000); // give Task.run() a change to run
      } catch (InterruptedException e) {
          e.printStackTrace();
      }
      task.stop();
      try {
          thread.join();
      } catch (InterruptedException e) {
          e.printStackTrace();
      }
      verify(mockAlerter,atLeastOnce()).alert();
      verify(mockAlerter,never()).harmless();
  
  }
  
  @Test
  public void testRunNoFeed() {
      Alerter mockAlerter=mock(Alerter.class);
      Task task=new Task(mockAlerter);
      Thread thread =new Thread(task);
      thread.start();
      try {
          Thread.sleep(1000);
      } catch (InterruptedException e) {
          e.printStackTrace();
      }
      changeFileSize();
      try {
          Thread.sleep(6000); //because every 5000ms file size will be checked once in run()
      } catch (InterruptedException e) {
          e.printStackTrace();
      }
  
      task.stop();
      try {
          thread.join();
      } catch (InterruptedException e) {
          e.printStackTrace();
      }
      verify(mockAlerter,atLeastOnce()).alert();
      verify(mockAlerter,atLeastOnce()).harmless();
  
  }
  </code></pre>
  
  <p>Thanks in advance.</p>