Mockito 的 anyString(), any(Foo.class) 等不能匹配 null 值

使用 Mockito Mock 方法式,一直以为可以用 anyString(), any(Foo.class) 等匹配 null 值,其实不行,null 值必须显式的用 null, 或 eq(null) 来匹配。anyString(), anyInt() 等只能匹配非 null 值,查看它们的返回值实际是 "" 和 0 等, 而更为特别的是 any(Foo.class) 看到的是 null, 仍然不能匹配 null 值。进一步用 Mockito.mockingDetails(mock).printInvocations() 打印出的内容,anyString(), any(Foo.class) 都会显示为 null 值。

说的有点罗嗦,看下面的例子, 被测试类 UserDao,sql 和 sqlArguments 由各自的 setter 方法来控制,默认它们都为 null

来它的测试类 UserDaoTest

测试不成功,输出信息为

java.lang.AssertionError:
Expected size:<2> but was:<0> in:
<[]>

空为 Mock 对象  namedParameterJdbcTemplate.query(...) 方法返回类型的默认值

原以为  anyString()any(MapSqlParameterSource.class) 可以匹配到实际中的 sql = null 和  sqlArguments = null 值,都说是 any 却不能对应到 null 值。如果在 assertThat(users).hasSize(2) 之前加上

再执行看到的输出为

[namedParameterJdbcTemplate.query(
    null,
    null,
    yanbin.blog.UserDao$$Lambda$1/1192672907@363a52f
);]

mockingDetails 告诉我们前两个参数的实际值为 null, 不能用 anyString()any(MapSqlParameterSource.class) 来匹配.

查看 ArgumentMatchers.anyString() 的值

似乎 anyString() 的值为 "", "" 不能匹配 null 值。断点调试中查看 anyString()  和 any(MapSqlParameterSourcec.class) 的值


注意,查看它们的值时会有异常,即 reportMatcher 报告出来的。

看起来  ArgumentMatchers.any(MapSqlParameterSource.class) 像是个真的 null 值,所以我们下面只把 anyString() 换成 eq(null) 来看下

还是不成功,同样的出错信息

java.lang.AssertionError:
Expected size:<2> but was:<0> in:
<[]>

实际运行中的两个 null 都必须用 null 值来匹配

测试通过。eq((MapSqlParameterSource)null) 中的转型是为了避免准确调用重载方法。

最后就是一句话,Mockito 中的 any 不是真正的 any, any 不代表 null,有点类似 SQLServer 中的某个字段(c1) 的值为 null 时,where c1 is null 可以查出来,但是用 where c1 in (null) 就查不出来了。

本文链接 https://yanbin.blog/mockito-anystring-anyfoo-class-cannot-match-null-values/, 来自 隔叶黄莺 Yanbin Blog

[版权声明] Creative Commons License 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。

Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments