首页 > 解决方案 > any(Classmember) 返回 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));

标签: javaunit-testingmockito

解决方案


我猜你正在尝试测试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方法而不是直接访问该字段,因为我的手指拒绝编写直接访问公共字段的代码:-)

如果您正在努力验证是否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方法中的设置代码分开。我只是把它放在一个测试中以保持答案简单。


推荐阅读