单元测试取消改造调用

Unittesting the cancellation of a retrofit call

我正在尝试编写一个单元测试来测试 Retrofit 调用的取消,但我卡住了。

实现如下:

public class LoginInteractorImpl extends AbstractInteractor implements LoginInteractor {

    private volatile Call<ResponseBody> mCall;

    private UserRepo mUserRepository;

    @Inject
    public LoginInteractorImpl(WorkerThread workerThread, MainThread mainThread,  UserRepo userRepository) {
        super(workerThread,mainThread);
        this.mUserRepository = userRepository;
    }

    @Override
    public void login(final String username, final String password, final OnLoginFinishedListener listener) {
    mWorkerThread.execute(new Runnable() {
            @Override
            public void run() {
                mCall = mUserRepository.doLogin(Credentials.basic(username, password));

                enqueue(new LoginCallbackImpl(mWorkerThread, mMainThread, listener));
            }
        });

    }

    @Override
    public void cancel() {
        if(mCall != null) {
            mCall.cancel();
        }
    }

    void enqueue(LoginCallback callback){
        mCall.enqueue(callback);
    }
}

这是我目前在测试课上得到的:

public class LoginInteractorTest {

    private LoginInteractorImpl mLoginInteractor;

    @Mock
    UserRepo mockUserRepository;

    @Mock
    private Call<ResponseBody> mockCall;

    @Mock
    private LoginInteractor.OnLoginFinishedListener mockLoginListener;

    @Before
    public void setUp() throws Exception {

        MockitoAnnotations.initMocks(this);

        mLoginInteractor = new LoginInteractorImpl(new FakeWorkerThread(), new FakeMainThread(), mockUserRepository);
    }

    ...

    @Test
    public void shouldCancelLoginCall() throws Exception {

        final String username = "test";
        final String password = "testtest";

        LoginInteractorImpl spy = Mockito.spy(mLoginInteractor);

        when(mockUserRepository.doLogin(anyString()))
            .thenReturn(mockCall);

        final CountDownLatch latch = new CountDownLatch(1);

        // Somehow delay the call and cancel it instead?

        when(mLoginInteractor.enqueue(any(LoginCallback.class)))
            .thenAnswer(
                // Somehow pospone the call from executing
            );

        // Enqueue logincall
        mLoginInteractor.login(username, password, mockLoginListener);

        // Cancel call
        mLoginInteractor.cancel();

        // Verify that cancel was called
        verify(mockCall, times(1)).cancel();
    }
}

我的问题是如何停止执行 mockCall 并验证我是否已成功取消?我最好的选择是我必须以某种方式使用 CountDownLatch,但我以前从未使用过它,并且无法在任何地方找到并回答如何在我的用例中使用它。

自己找到答案:

public void shouldCancelLoginCall() throws Exception {

    final String username = "test";
    final String password = "testtest";

    LoginInteractorImpl spy = Mockito.spy(mLoginInteractor);

    when(mockUserRepository.doLogin(anyString())).thenReturn(mockCall);

    doNothing().when(spy).enqueue(any(LoginCallback.class));

    mLoginInteractor.login(username, password, mockLoginListener);

    mLoginInteractor.cancel();

    verify(mockCall, times(1)).cancel();
}