任何(班级成员)returns null mockito

any(Classmember) returns null mockito

我正在尝试执行 when().thenReturn() 但遇到问题。以下是我为 SOers 编写的示例代码:

import java.util.List;

public class Sample {
    public void function(List<SampleA> list) {
        for (SampleA s : list) {
            List<SampleB> nameList = s.v1;
            for (SampleB m : nameList) {
                SampleC value = m.getV2();
                if (value != null) {
                    doSomething(value);
                } else {
                    LOGGER.warn("No valid value");
                }
            }
        }
    }
}

public class SampleA{
    List<SampleB> v1;
}

public class SampleB{
    SampleC v2;

    public SampleC getV2(){
        return this.v2;
    }
}

这可能很愚蠢,但我只是想了解为什么我不能这样做:

SampleB sampleB = new SampleB();
when(sampleB.getV2()).thenReturn(any(SampleC.class));

any(…) 是一个 ArgumentMatcher。它用于匹配参数。您不能将它用于 类 的 return 个实例。 “任何 SampleC”会是什么?

您可以将它与模拟对象一起使用,如下所示:

SampleInterface sample = Mockito.mock(SampleInterface.class);
when(sample.function(any(List.class))).thenReturn(new ArrayList<>());
// or: .thenAnswer(a -> new ArrayList<>()); to return a new instance for each call

您不能在 thenReturn 或 thenAnswer 中使用 ArgumentMatchers。您必须准确指定 return 的内容。例如:

SampleB sampleB = mock(SampleB.class)
when(sampleB.getV2()).thenReturn(new SampleC());

我猜您正在尝试测试 Sample.function 并试图弄清楚如何模拟 SampleC 值。如果是这样,那么您的代码可能应该类似于:

@Test
void testFunction() {
    SampleC mockC = mock(SampleC.class);
    SampleB mockB = mock(SampleB.class);
    SampleA mockA = mock(SampleA.class);
    when(mockB.getV2()).thenReturn(mockC);
    when(mockA.getV1()).thenReturn(List.of(mockB));
    Sample sample = new Sample();
    sample.function(List.of(mockA));
    // verify doSomething was called with mockC as its argument
    when(mockB.getV2()).thenReturn(null);
    sample.function(List.of(mockA));
    // verify "No valid value" was logged
}

我添加了一个 getV1 方法而不是直接访问字段,因为我的手指拒绝编写直接访问 public 字段的代码:-)

如果您正在努力验证 doSomething 是否被调用,那么这就是参数匹配的用武之地。理想情况下,您可以将 SomethingDoer 注入样本中:

interface SomethingDoer {
    void doSomething(SampleC sample);
}

class Sample {
    private final SomethingDoer somethingDoer;

    public Sample(SomethingDoer somethingDoer) {
        this.somethingDoer = somethingDoer;
    }
}

然后将以下内容添加到测试中:

SomethingDoer doer = mock(SomethingDoer.class);
Sample sample = new Sample(doer);
...
verify(doer).doSomething(mockC);

另请注意,上面的代码风格不佳:测试应与 @BeforeEach 方法中的设置代码分开。我只是将它放在一个测试中以保持答案简单。