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) 就查不出来了。

类别: Java/JEE. 标签: . 阅读(184). 订阅评论. TrackBack.
guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x