使用Mockito,如何验证方法是否具有某个参数?

Dav*_*ave 52 java mocking mockito

我正在使用Mockito 1.9.0.我如何验证一个方法只被调用一次,并且传递给它的一个字段包含一定的值?在我的JUnit测试中,我有

@Before
public void setupMainProg() { 
    // Initialize m_orderSvc, m_opportunitySvc, m_myprojectOrgSvc
    ...
    m_prog = new ProcessOrdersWorker(m_orderSvc, m_opportunitySvc, m_myprojectOrgSvc);
}   // setupMainProg

@Test
public void testItAll() throws GeneralSecurityException, IOException { 
    m_prog.work();  
}
Run Code Online (Sandbox Code Playgroud)

方法"work"调用"m_orderSvc"方法(传递给对象的参数之一)."m_orderSvc"又包含一个成员字段"m_contractsDao".我想验证"m_contractsDao.save"只被调用一次,并且传递给它的参数包含一个特定值.

这可能有点令人困惑.让我知道如何澄清我的问题,我很高兴这样做.

mam*_*ing 58

首先,您需要创建一个模拟m_contractsDao并进行设置.假设该类是ContractsDao:

ContractsDao mock_contractsDao = mock(ContractsDao.class);
when(mock_contractsDao.save(any(String.class))).thenReturn("Some result");
Run Code Online (Sandbox Code Playgroud)

然后将模拟注入m_orderSvc并调用您的方法.

m_orderSvc.m_contractsDao = mock_contractsDao;
m_prog = new ProcessOrdersWorker(m_orderSvc, m_opportunitySvc, m_myprojectOrgSvc);
m_prog.work(); 
Run Code Online (Sandbox Code Playgroud)

最后,验证模拟是否被正确调用:

verify(mock_contractsDao, times(1)).save("Parameter I'm expecting");
Run Code Online (Sandbox Code Playgroud)

  • 仅供参考,你可以放弃`,次(1)`,因为它总是暗示,除非你添加一个量词指定除了一次以外的东西.而不是`any(String.class)`,有一​​个更方便的`anyString()`. (10认同)
  • 值得注意的是,传递给AFTER`verify`方法的参数使用`equals`与实际测试期间传递的参数进行比较.因此,无论方法是什么(mamboking示例中的`save`方法),考虑每个参数的_type_,以及与`equals`的比较是否是您真正想要的.如果你想在参数比`equals`其他东西进行测试,你需要某种类型的`ArgumentMatcher`(这可能是一个'ArgumentCaptor`在凯文·韦尔克的答案). (3认同)

Kev*_*ker 25

建立Mamboking的答案:

ContractsDao mock_contractsDao = mock(ContractsDao.class);
when(mock_contractsDao.save(anyString())).thenReturn("Some result");

m_orderSvc.m_contractsDao = mock_contractsDao;
m_prog = new ProcessOrdersWorker(m_orderSvc, m_opportunitySvc, m_myprojectOrgSvc);
m_prog.work(); 
Run Code Online (Sandbox Code Playgroud)

解决您的请求以验证参数是否包含某个值,我可以假设您的意思是该参数是一个String,并且您想要测试String参数是否包含子字符串.为此您可以这样做:

ArgumentCaptor<String> savedCaptor = ArgumentCaptor.forClass(String.class);
verify(mock_contractsDao).save(savedCaptor.capture());
assertTrue(savedCaptor.getValue().contains("substring I want to find");
Run Code Online (Sandbox Code Playgroud)

如果这个假设是错误的,并且参数save()是某种类型的集合,那么它只会略有不同:

ArgumentCaptor<Collection<MyType>> savedCaptor = ArgumentCaptor.forClass(Collection.class);
verify(mock_contractsDao).save(savedCaptor.capture());
assertTrue(savedCaptor.getValue().contains(someMyTypeElementToFindInCollection);
Run Code Online (Sandbox Code Playgroud)

如果您知道如何使用Hamcrest匹配器,您也可以检查ArgumentMatchers.


thu*_*mer 10

这是更好的解决方案:

verify(mock_contractsDao, times(1)).save(Mockito.eq("Parameter I'm expecting"));
Run Code Online (Sandbox Code Playgroud)