我可以混合Argument Captor和常規匹配器嗎?

[英]Can I mix Argument Captor and a regular matcher?


I need to verify a method with multiple parameter in Mockito, but need to capture only one argument, the others I need only a simple matcher. Is that possible?

我需要在Mockito中驗證一個帶有多個參數的方法,但需要只捕獲一個參數,其他我只需要一個簡單的匹配器。那可能嗎?

For instance, if I have:

例如,如果我有:

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

In this case do I need to write a captor for each argument in spite of the fact I need to capture only the first argument?

在這種情況下,我是否需要為每個參數編寫一個captor,盡管我只需捕獲第一個參數?

2 个解决方案

#1


17  

In this case do I need to write a captor for each argument in spite of the fact I need to capture only the first argument?

在這種情況下,我是否需要為每個參數編寫一個captor,盡管我只需捕獲第一個參數?

durron597's answer is correct—you do not need to capture all arguments if you want to capture one of them. One point of clarification, though: a call to ArgumentCaptor.capture() counts as a Mockito matcher, and in Mockito if you use a matcher for any method argument you do have to use a matcher for all arguments.

durron597的答案是正確的 - 如果你想捕獲其中一個,你不需要捕獲所有參數。但有一點澄清:對ArgumentCaptor.capture()的調用計為Mockito匹配器,而在Mockito中如果使用匹配器進行任何方法參數,則必須對所有參數使用匹配器。

For a method yourMock.yourMethod(int, int, int) and an ArgumentCaptor<Integer> intCaptor:

對於方法yourMock.yourMethod(int,int,int)和ArgumentCaptor 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));

These also work:

這些也有效:

verify(yourMock).yourMethod(intCaptor.capture(), eq(5), otherIntCaptor.capture());
verify(yourMock).yourMethod(intCaptor.capture(), anyInt(), gt(9000));

#2


2  

Of course it works. Why wouldn't it?

當然有效。為什么不呢?

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());
  }
}

This works correctly and passes.

這工作正常並通過。


As an aside, you almost never want to mock data structures such as List and Map, because it's a giant pain to correctly mock all their behavior and most code won't be very happy if you, for example, add an element and then the element doesn't actually exist. In your case, it would probably be better to create a partial mock (using Mockito.spy) than an actual mock.

順便說一句,你幾乎從不想模擬像List和Map這樣的數據結構,因為正確地模擬它們的所有行為是一件巨大的痛苦,如果你添加一個元素然后然后大多數代碼都不會很高興。元素實際上並不存在。在您的情況下,創建部分模擬(使用Mockito.spy)可能比實際模擬更好。


注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2015/09/22/72a195b17286d64a8d102b6cabcb4502.html



 
粤ICP备14056181号  © 2014-2020 ITdaan.com