Can Mockito capture arguments of a method called multiple times?
我有一个方法被调用两次,我想捕获第二个方法调用的参数。
以下是我的尝试:
1 2 3 4 5 | ArgumentCaptor<Foo> firstFooCaptor = ArgumentCaptor.forClass(Foo.class); ArgumentCaptor<Foo> secondFooCaptor = ArgumentCaptor.forClass(Foo.class); verify(mockBar).doSomething(firstFooCaptor.capture()); verify(mockBar).doSomething(secondFooCaptor.capture()); // then do some assertions on secondFooCaptor.getValue() |
但我得到了一个
如何验证
我想应该是
1 | verify(mockBar, times(2)).doSomething(...) |
Mockito Javadoc的样品:
1 2 3 4 5 6 | ArgumentCaptor<Person> peopleCaptor = ArgumentCaptor.forClass(Person.class); verify(mock, times(2)).doSomething(peopleCaptor.capture()); List<Person> capturedPeople = peopleCaptor.getAllValues(); assertEquals("John", capturedPeople.get(0).getName()); assertEquals("Jane", capturedPeople.get(1).getName()); |
由于mockito 2.0,还可以使用静态方法matchers.arghat(argumentmatcher)。在Java 8的帮助下,它现在变得更干净,更易于阅读:
1 2 | verify(mockBar).doSth(argThat((arg) -> arg.getSurname().equals("OneSurname"))); verify(mockBar).doSth(argThat((arg) -> arg.getSurname().equals("AnotherSurname"))); |
如果你被绑定到较低的Java版本,也没有那么糟糕:
1 2 3 4 5 6 | verify(mockBar).doSth(argThat(new ArgumentMatcher<Employee>() { @Override public boolean matches(Object emp) { return ((Employee) emp).getSurname().equals("SomeSurname"); } })); |
当然,这些都不能验证通话顺序—您应该使用inorder:
1 2 3 4 | InOrder inOrder = inOrder(mockBar); inOrder.verify(mockBar).doSth(argThat((arg) -> arg.getSurname().equals("FirstSurname"))); inOrder.verify(mockBar).doSth(argThat((arg) -> arg.getSurname().equals("SecondSurname"))); |
请看一下mockito-java8项目,它可以进行如下调用:
1 | verify(mockBar).doSth(assertArg(arg -> assertThat(arg.getSurname()).isEqualTo("Surname"))); |
如果您不想验证所有对
如果多次调用该方法,则返回最新捕获的值
所以这是可行的(假设
1 2 3 4 | ArgumentCaptor<Foo> fooCaptor = ArgumentCaptor.forClass(Foo.class); verify(mockBar, times(2)).doSomething(fooCaptor.capture()); //getValue() contains value set in second call to doSomething() assertEquals("2nd one", fooCaptor.getValue().getName()); |
也可以使用@captor注释的argumentcaptor。例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | @Mock List<String> mockedList; @Captor ArgumentCaptor<String> argCaptor; @BeforeTest public void init() { //Initialize objects annotated with @Mock, @Captor and @Spy. MockitoAnnotations.initMocks(this); } @Test public void shouldCallAddMethodTwice() { mockedList.add("one"); mockedList.add("two"); Mockito.verify(mockedList, times(2)).add(argCaptor.capture()); assertEquals("one", argCaptor.getAllValues().get(0)); assertEquals("two", argCaptor.getAllValues().get(1)); } |
用Java 8的lambdas,一个方便的方法就是使用
1 2 3 4 5 6 | org.mockito.invocation.InvocationOnMock when(client.deleteByQuery(anyString(), anyString())).then(invocationOnMock -> { assertEquals("myCollection", invocationOnMock.getArgument(0)); assertThat(invocationOnMock.getArgument(1), Matchers.startsWith("id:")); } |