任何()与任何(Class.class)Mockito

any() vs any(Class.class) Mockito

我无法理解为什么下面的两个测试没有给出相同的结果。

@Service
public class SomeManager{
    private final SomeDependency someDependency;
    
    @Autowired
    public SomeManager(SomeDependency someDependency){
        this.someDependency = someDependency;
    }
    
    public List<returnType> methodToTest(Arg arg){
        List<JsonObject> jo = someDependency.search(arg);
        return jo.stream().map(returnType::parse).collect(Collectors.toList());

    }
}

any() 测试。本次测试通过。

@RunWith(SpringJUnit4ClassRunner.class)
public class TestMethodToTest(){
    @Test
    public void TestMethod(){
        SomeDependency someDependency = mock(SomeDependency.class);
        List<JsonObject> expected := \some valid list of JsonObject\
    
        // Here I used any() method.
        when(someDependency.search(any())).thenReturn(expected);
    
        SomeManager someManager = new SomeManager(someDependency);
        List<returnType> actual = someManager.methodToTest(any(Arg.class));
    
        assertArrayEquals(acutal.toArray(), expected.stream().map(returnType::parse).toArray());
        }
}

但是由于 SomeDependencysearch(Arg arg) 方法采用 class Arg 的参数,所以我将上面的测试更改为:

@RunWith(SpringJUnit4ClassRunner.class)
public class TestMethodToTest(){
    @Test
    public void TestMethod(){
        SomeDependency someDependency = mock(SomeDependency.class);
        List<JsonObject> expected := \some valid list of JsonObject\

        // Here I used any(Arg.class) method.
        when(someDependency.search(any(Arg.class))).thenReturn(expected);
    
        SomeManager someManager = new SomeManager(someDependency);
        List<returnType> actual = someManager.methodToTest(any(Arg.class));
    
        assertArrayEquals(acutal.toArray(), expected.stream().map(returnType::parse).toArray());
        }
}

第二次测试失败并输出 java.lang.AssertionError: array lengths differed, expected.length=1 actual.length=0。这背后的可能原因是什么?

注意:输出中的值 expected.length=1 取决于用户提供的值作为测试中 json 对象的有效列表。

区别在于any匹配null,而anyClass不匹配null。见 ArgumentMatchers javadoc:

  • any() 匹配任何内容,包括空值和可变参数。
  • any​(Class<T> type) 匹配给定类型的任何对象,不包括空值。

您正在将 null 传递给您在此处测试的方法:

List<returnType> actual = someManager.methodToTest(any(Arg.class));

any() returns 您传递给被测方法的 null。

请注意,以这种方式使用参数匹配器是非法的 - 您只能在对 whenverify 的调用中调用它们。您应该将 Arg 的真实实例传递给被测方法。

Mockito javadoc

Matcher methods like any(), eq() do not return matchers. Internally, they record a matcher on a stack and return a dummy value (usually null). This implementation is due to static type safety imposed by the java compiler. The consequence is that you cannot use any(), eq() methods outside of verified/stubbed method.