Mockito: wait for an invocation that matches arguments

前端 未结 2 1532
盖世英雄少女心
盖世英雄少女心 2021-01-07 17:22

I\'m writing a selenium test and verifying the server behavior with mockito. Specifically, when a button is clicked, I want to make sure the page controller calls a particul

相关标签:
2条回答
  • 2021-01-07 17:41

    If you are able to set a fixed number of calls to expect, it can be done with an ArgumentCaptor:

    import static org.hamcrest.CoreMatchers.hasItem;
    
    @Captor ArgumentCaptor<String> arg;
    
    @Before
    public void setUp() throws Exception {
        // init the @Captor
        initMocks(this);
    }
    
    @Test
    public void testWithTimeoutCallOrderDoesntMatter() throws Exception {
        // there must be exactly 99 calls
        verify(myMock, timeout(5000).times(99)).myMethod(arg.capture());
        assertThat(arg.getAllValues(), hasItem("expectedArg"));
    }
    

    Another way is to specify all the expected values to verify, but those need to be provided in the exact order that they are invoked. The difference to the above solution is that this doesn't fail even if the mock is additionally called with some non-verified arguments. In other words, no need to know the number of total invocations. Code example:

    @Test
    public void testWithTimeoutFollowingCallsDoNotMatter() throws Exception {
        // the order until expected arg is specific
        verify(callback, timeout(5000)).call("firstExpectedArg");
        verify(callback, timeout(5000)).call("expectedArg");
        // no need to tell more, if additional calls come after the expected arg
        // verify(callback, timeout(5000)).call("randomArg");
    }
    
    0 讨论(0)
  • 2021-01-07 17:43

    This is not a super clean solution but you can do this (XX is the supposed return type here):

    final CountDownLatch latch = new CountDownLatch(1);
    
    doReturn(new Answer<XX>()
        {
            @Override
            public XX answer(InvocationOnMock invocation)
            {
                latch.countDown();
                return someInstanceOfXX;
            }
        }
    ).when(myMock).myMethod("expectedArg");
    

    Then, to test if the method is called, do:

    try {
        assertTrue(latch.await(5L, TimeUnit.SECONDS));
    } catch (InterruptedException e) {
        // Urgh... Failed. Deal with it and:
        Thread.currentThread.interrupt();
    }
    
    0 讨论(0)
提交回复
热议问题