我需要在Mockito中验证一个带有多个参数的方法,但需要只捕获一个参数,其他我只需要一个简单的匹配器。这可能吗?
例如,如果我有:
@Mock
private Map<K,V> mockedMap;
...
ArgumentCaptor<K> argument = ArgumentCaptor.forClass(K.class);
verify(mockedMap).put(argument.capture(), any(V.class));
在这种情况下,我是否需要为每个参数编写一个captor,尽管我只需捕获第一个参数?
答案 0 :(得分:24)
在这种情况下,我是否需要为每个参数编写一个captor,尽管我只需捕获第一个参数?
durron597's answer是正确的 - 如果要捕获其中一个参数,则不需要捕获所有参数。但有一点需要澄清:对ArgumentCaptor.capture()
的调用计为Mockito匹配器,如果使用 matcher 进行任何方法参数you do have to use a matcher for all arguments,则调用Mockito。
对于方法yourMock.yourMethod(int, int, int)
和ArgumentCaptor<Integer> intCaptor
:
/* good: */ verify(yourMock).yourMethod(2, 3, 4); // eq by default
/* same: */ verify(yourMock).yourMethod(eq(2), eq(3), eq(4));
/* BAD: */ verify(yourMock).yourMethod(intCaptor.capture(), 3, 4);
/* fixed: */ verify(yourMock).yourMethod(intCaptor.capture(), eq(3), eq(4));
这些也有效:
verify(yourMock).yourMethod(intCaptor.capture(), eq(5), otherIntCaptor.capture());
verify(yourMock).yourMethod(intCaptor.capture(), anyInt(), gt(9000));
答案 1 :(得分:2)
当然有效。为什么不呢?
import java.util.Map;
import org.junit.*;
import org.mockito.*;
import static org.mockito.Mockito.*;
import static org.junit.Assert.*;
public class MockitoTest {
@Mock
private Map<Integer, String> mockedMap;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
@Test
public void testCaptor() {
mockedMap.put(5, "Hello World!");
ArgumentCaptor<Integer> argument = ArgumentCaptor.forClass(Integer.class);
verify(mockedMap).put(argument.capture(), any(String.class));
assertEquals(5L, argument.getValue().longValue());
}
}
这可以正常工作并通过。
顺便说一句,你几乎不想模仿List
和Map
之类的数据结构,因为正确地模拟他们的所有行为是一件巨大的痛苦,而且大多数代码都不会很高兴例如,您添加一个元素,然后该元素实际上不存在。在您的情况下,创建部分模拟(使用Mockito.spy
)可能比实际模拟更好。
答案 2 :(得分:0)
至少对于Mockito 1.10.19,您需要为所有参数传递一个捕获器。
因此,除了杰夫·鲍曼(Jeff Bowman)的答案之外,如果您甚至需要捕获单个参数,就需要执行以下操作:
verify(yourMock).yourMethod(intCaptor.capture(), otherIntCaptor.capture(), otherIntCaptor.capture());