我有这个代码:
import static org.mockito.Mockito.*;
final Combobox combobox = mock(Combobox.class);
//.... some business logic which calls method 'appendChild' on 'combobox'
verify(combobox, times(3)).appendChild((Component) anyObject()); // <<== exception here
它一直写着:
Invalid use of argument matchers!
2 matchers expected, 1 recorded.
This exception may occur if matchers are combined with raw values:
//incorrect:
someMethod(anyObject(), "raw String");
When using matchers, all arguments have to be provided by matchers.
For example:
//correct:
someMethod(anyObject(), eq("String by matcher"));
For more info see javadoc for Matchers class.
appendChild方法如下:
public final boolean appendChild(Component child)
{
return insertBfr(null, child);
}
appendChild
是一个final方法,这意味着你不能模拟或验证它。Java编译器理解"final"意味着它可以确定它调用的是哪一个实际的方法实现,也就是说它可以走捷径直接调用代码,而不是让Mockito偷偷进入并替换实现。一般来说,这是人们建议不要嘲笑你不拥有或控制的类型的好理由之一。
重构测试,或者使用PowerMockito执行深层字节码魔术来模拟那些最终的方法。
(为什么会出现这种异常?匹配器实际上会影响Mockito中的静态状态。因为你在那一行调用了anyObject
,所以Mockito仍然注册了一个匹配器。该匹配器在你下一次调用when
或verify
时匹配一个不存在的参数,或者如果你使用MockitoJUnitRunner
,则会被Mockito使用验证器捕获。无论哪种方式,这都是一个很好的捕获,因为代码并没有按照你认为的那样做。)