【问题标题】:Can I mix Argument Captor and a regular matcher?我可以混合使用 Argument Captor 和常规匹配器吗?
【发布时间】:2023-03-16 22:57:02
【问题描述】:

我需要在 Mockito 中验证具有多个参数的方法,但只需要捕获一个参数,其他我只需要一个简单的匹配器。这可能吗?

例如,如果我有:

@Mock
private Map<K,V> mockedMap;
...
ArgumentCaptor<K> argument = ArgumentCaptor.forClass(K.class);
verify(mockedMap).put(argument.capture(), any(V.class));

在这种情况下,尽管我只需要捕获第一个参数,但我是否需要为每个参数编写一个捕获器?

【问题讨论】:

    标签: java junit mockito


    【解决方案1】:

    在这种情况下,尽管我只需要捕获第一个参数,但我是否需要为每个参数编写一个捕获器?

    durron597's answer 是正确的——如果要捕获其中一个参数,则不需要捕获所有参数。不过需要澄清一点:对 ArgumentCaptor.capture() 的调用算作 Mockito 匹配器,在 Mockito 中,如果您将 matcher 用于任何方法参数 you do have to use a matcher for all arguments

    对于方法yourMock.yourMethod(int, int, int)ArgumentCaptor&lt;Integer&gt; 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));
    

    【讨论】:

    • 这真的很有帮助:)
    【解决方案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());
      }
    }
    

    这可以正常工作并通过。


    顺便说一句,您几乎从不想模拟 ListMap 之类的数据结构,因为正确模拟它们的所有行为是一件非常痛苦的事情,而且大多数代码不会很高兴,例如,添加一个元素,然后该元素实际上并不存在。在您的情况下,创建部分模拟(使用Mockito.spy)可能比实际模拟更好。

    【讨论】:

      【解决方案3】:

      至少对于 Mockito 1.10.19,您需要为所有参数传递一个捕获者。

      因此,添加到 Jeff Bowman 的答案中,如果您需要捕获甚至一个参数,您需要这样做:

      verify(yourMock).yourMethod(intCaptor.capture(), otherIntCaptor.capture(), otherIntCaptor.capture());
      

      【讨论】:

      • 我没有看到任何需要捕获所有论点的行为。您是否有一个方便的测试用例来显示您需要在哪里为所有参数传递一个捕获器(而不是匹配器)?
      猜你喜欢
      • 2012-03-13
      • 1970-01-01
      • 2016-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多