Calling callbacks with Mockito

前端 未结 4 1826
梦毁少年i
梦毁少年i 2020-11-28 07:36

I have some code

service.doAction(request, Callback callback);

How can I using Mockito grab the callback object, and call c

4条回答
  •  情书的邮戳
    2020-11-28 08:02

    Consider using an ArgumentCaptor, which in any case is a closer match to "grab[bing] the callback object".

    /**
     * Captor for Response callbacks. Populated by MockitoAnnotations.initMocks().
     * You can also use ArgumentCaptor.forClass(Callback.class) but you'd have to
     * cast it due to the type parameter.
     */
    @Captor ArgumentCaptor> callbackCaptor;
    
    @Test public void testDoAction() {
      // Cause service.doAction to be called
    
      // Now call callback. ArgumentCaptor.capture() works like a matcher.
      verify(service).doAction(eq(request), callbackCaptor.capture());
    
      assertTrue(/* some assertion about the state before the callback is called */);
    
      // Once you're satisfied, trigger the reply on callbackCaptor.getValue().
      callbackCaptor.getValue().reply(x);
    
      assertTrue(/* some assertion about the state after the callback is called */);
    }
    

    While an Answer is a good idea when the callback needs to return immediately (read: synchronously), it also introduces the overhead of creating an anonymous inner class, and unsafely casting the elements from invocation.getArguments()[n] to the data type you want. It also requires you to make any assertions about the pre-callback state of the system from WITHIN the Answer, which means that your Answer may grow in size and scope.

    Instead, treat your callback asynchronously: Capture the Callback object passed to your service using an ArgumentCaptor. Now you can make all of your assertions at the test method level and call reply when you choose. This is of particular use if your service is responsible for multiple simultaneous callbacks, because you have more control over the order in which the callbacks return.

提交回复
热议问题