Java 使用Mockito,我如何验证方法是使用某个参数调用的?

Java 使用Mockito,我如何验证方法是使用某个参数调用的?,java,mocking,mockito,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_m

我正在使用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();  
}
方法“work”调用“m_orderSvc”(传入对象的参数之一)的方法。“m_orderSvc”又包含一个成员字段“m_contractsDao”。我想验证“m_contractsDao.save”是否只调用了一次,并且传递给它的参数是否包含某个值


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

首先,您需要创建一个模拟m_合同DAO并进行设置。假设该类为ContractsDao:

ContractsDao mock\u ContractsDao=mock(ContractsDao.class);
当(mock_contractsDao.save(any(String.class)),然后返回(“某个结果”);
然后将mock注入m_orderSvc并调用您的方法

m_orderSvc.m_contractsDao=mock_contractsDao;
m_prog=新的ProcessOrdersWorker(m_orderSvc、m_opportunitySvc、m_myprojectOrgSvc);
m_prog.work();
最后,验证是否正确调用了模拟:

verify(mock_contractsDao,times(1)).save(“我期望的参数”);

根据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(); 
处理验证参数是否包含某个值的请求时,我可以假设您的意思是该参数是字符串,并且您希望测试该字符串参数是否包含子字符串。为此,您可以:

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

如果您知道如何使用Hamcrest matchers,您还可以查看。这是更好的解决方案:

verify(mock_contractsDao, times(1)).save(Mockito.eq("Parameter I'm expecting"));

仅供参考,您可以省略
,times(1)
,因为它总是隐含的,除非您添加一个量词来指定非一次性的内容。与
any(String.class)
不同,这里有一个稍微方便的
anyString()
。还值得注意的是,在
verify
之后传递给方法的参数使用
equals
与实际测试中传递的参数进行比较。因此,无论是什么方法(mamboking示例中的
save
方法),都要考虑每个参数的类型,以及与
的比较是否等于
。如果你想用
equals
以外的东西来测试论点,你需要某种
ArgumentMatcher
(可能是Kevin Welker的答案中的
ArgumentCaptor
)。如何精确指定一次,而不是两次或更多@KevinWelker的评论说它是隐式的,但不确定它的意思是只传递一次,还是至少传递一次。除了传递我所期望的确切参数,有没有办法在可能传递给方法的参数上传递谓词?例如,
verify(mock_contractsDao,times(1)).save((字符串s)->s.length()==23)?我还没有在Mockito 2.x中尝试过任何东西,但是您可能会在新的ArgumentMatcher中找到您想要的东西。此语法可能不正确,但以下内容可能接近您在Mockito 2.x下所需的内容:
verify(mock_contractsDao).save(argThat(s->s.length==23))这在处理非基本类型时更好。
verify(mock_contractsDao, times(1)).save(Mockito.eq("Parameter I'm expecting"));