User Mockito to unit test a function doing async t

2020-03-08 05:51发布

问题:

In my Android project, I have a class extends HandlerThread:

public class MyHandlerThread extends HandlerThreads {
   private Handler mHandler;
   …
   public void doAsyncTask(MyAsyncTask task) {
        mHandler = new Handler(this.getLooper());
        mHandler.post(task);
    }
}

The above function's parameter type MyAsyncTask is a class extends Runnable:

public abstract class MyAsyncTask implements Runnable {
    @Override
    public void run() {
        doTask();
    }

    public abstract void doTask();
}

I have a MyWorker class which has a function uses MyHandlerThread class:

public class MyWorker {

  public void work() {
      MyHandlerThread handlerThread = new MyHandlerThread();
      handlerThread.start();
      handlerThread.doAsyncTask(new MyAsyncTask() {
           @Override
           doTask() {
               int responseCode = sendDataToServer();
           }
      });
  }
}

I want to use Mockito to unit test the work() function in MyWorker class (e.g. check the server responseCode). How to do it in Mockito?

回答1:

WHAT do you want to test? MyWorker? MyHandlerThread? the anonymous MyAsyncTask? All toegether? Probably a bad idea, especially if the anonymous MyAsyncTask relies on an actual server response (which would prevent this from being a good unit test, since you are testing a whole system then). So, I would split the whole thing into parts and test all these parts seperately. If you have done so, then you can check multiple parts toegether against a real server with an integration tests.

To test the MyHandlerThread, you could for example introduce a HandlerFactory, mock that and thus ensure that the handler was called correctly.

public class MyHandlerThread extends HandlerThreads {
   private HandlerFactory handlerFactory; // <- Add setter
   …
   public void doAsyncTask(MyAsyncTask task) {
        Handler mHandler = handlerFactory.createHandler(this.getLooper());
        mHandler.post(task);
    }
}

Easily testable unit. MyAsyncTask is short and abstract, honestly, I wouldn't test that. Not much to gain there, since it doesn't actually do much. And the MyWorker ? Depends, but you could, for example, add a getter/setter for the MyHandlerThread, allowing you to mock that. Extracting your anonymous class into a real one would probably allow you to test that one, too, independent of the others.