Mockito报错‘Only void methods can doNothing()’:void方法模拟失败排查
你遇到的问题核心是方法重载导致Mockito匹配到了非void的重载方法。尽管你目标的setStructured是void类型,但SQLServerPreparedStatement类中可能存在其他同名但返回值非void的setStructured重载方法。当你使用参数匹配器(如Mockito.isA(...))时,Mockito无法精准匹配到你要模拟的void版本,误匹配到了带返回值的重载方法,从而抛出“Only void methods can doNothing()!”错误。
针对这个问题,有几种可行的解决方式:
1. 去掉不必要的doNothing()调用
Mockito对模拟对象的void方法默认行为就是“什么都不做”,所以你完全可以删掉这句显式的doNothing()代码,直接调用目标方法即可,不会影响测试逻辑。
修改后的代码片段:
// 无需显式模拟doNothing,默认行为就是无操作 mockStatement.setStructured(1, Mockito.isA(String.class), Mockito.isA(SQLServerDataTable.class));
2. 显式指定要匹配的void方法签名
如果必须保留doNothing()(比如后续可能要修改为模拟异常),可以通过显式指定泛型类型来让Mockito精准匹配到void版本的方法:
Mockito.doNothing().when(mockStatement).<void>setStructured(1, Mockito.isA(String.class), Mockito.isA(SQLServerDataTable.class));
3. 使用更精确的参数匹配
避免使用宽泛的isA()匹配器,改用更具体的参数值或匹配方式,帮助Mockito精准定位到目标重载方法。例如:
// 如果知道tvpName的具体值,可以直接传入 Mockito.doNothing().when(mockStatement).setStructured(1, "your_tvp_name", Mockito.any(SQLServerDataTable.class));
你可以通过查看SQLServerPreparedStatement的类文档或反编译代码,确认是否存在setStructured的重载方法。比如,部分SQL Server JDBC驱动版本中,可能存在返回SQLServerPreparedStatement的链式调用重载(如setStructured(...)返回自身),这类方法的返回值非void,正是Mockito误匹配的目标。
内容的提问来源于stack exchange,提问作者Renaud

