如何在 Mockito.when().thenReturn() 中使用 ArgumentCaptor

dus*_*shu 5 java junit unit-testing arguments mockito

我有一个用例,我想捕获方法中传递的值,并使用此值来定义 Mockito 行为。

像这样 :

@InjectMocks
private ClassUnderTest classUnderTest;

@Mock
private MockedClass mockedClass;

@Captor
private ArgumentCaptor<ArgumentUsedInMockedClass> captor;

@Test
public void testMethod() {
    Result result = new Result();
    result.setResultId(RESULT_ID);

    Mockito.verify(mockedClass).doSomething(captor.capture());

    Mockito.when(mockedClass.doSomething(captor.getValue())).thenReturn(result);

    Assert.assertTrue(classUnderTest
            .doSomething(foo, bar)
            .equals(result));
}
Run Code Online (Sandbox Code Playgroud)

但我收到此错误:

[junit] Wanted but not invoked:
[junit] mockedClass.doSomething(
[junit]     <Capturing argument>
[junit] ); 
[junit] Actually, there were zero interactions with this mock.
Run Code Online (Sandbox Code Playgroud)

在我的doSomething()函数中, foo 和 bar 用于生成类型的参数ArgumentUsedInMockedClass。现在,这种ArgumentUsedInMockedClass类型没有equals()正确定义,因此如果我试图直接使用它,它会模糊地失败

Mockito.when(mockedClass.doSomething(argumentUsedInMockedClass)).thenReturn(result);argumentUsedInMockedClass测试方法的产生,即使它的PARAMS相同。我正在尝试捕获在此 ClassUnderTest 中创建的确切对象来定义模拟行为,但在我看来它就像一个循环,首先

Assert.assertTrue(classUnderTest
            .doSomething(foo, bar)
            .equals(result));
Run Code Online (Sandbox Code Playgroud)

必须碰巧实际捕获,但要使其工作,mockedClass应该定义取决于它的行为。

我如何解决这种情况或使用其他一些测试方法?

hot*_*zst 5

您收到错误是因为您尝试验证该方法是否在实际调用之前被调用,这发生在assertTrue.

你可以像这样重写你的测试:

@Test
public void testMethod() {
    Result result = new Result();
    result.setResultId(RESULT_ID);

    // Define the behavior
    Mockito.when(mockedClass.doSomething(any(ArgumentUsedInMockedClass.class)).thenReturn(result);

    Assert.assertTrue(classUnderTest
            .doSomething(foo, bar)
            .equals(result));
    Mockito.verify(mockedClass).doSomething(captor.capture());
    ArgumentUsedInMockedClass argument = captor.getValue();
    // Do some further verification/assertion with argument
}
Run Code Online (Sandbox Code Playgroud)