org.mockito.exceptions.misusing.InvalidUseOfMatchersException 尝试创建自定义参数匹配器时
org.mockito.exceptions.misusing.InvalidUseOfMatchersException when trying to create custom argument matcher
我正在使用 Mockito 1.10.18。我正在尝试为具有以下签名的方法创建自定义参数匹配器……
SaveResult[] com.sforce.soap.enterprise.EnterpriseConnection.update(SObject[] sObjects) throws ConnectionException
我编写了以下自定义参数匹配器……
class AccountMatcher extends ArgumentMatcher<SObject[]>
{
private Set<String> idList = new HashSet<String>();
AccountMatcher(final Set<Account> mainList)
{
for (final Account acct : mainList)
{
idList.add(acct.getId());
} // for
}
public boolean matches(Object param)
{
final SObject[] compSet = ((SObject[]) param);
final Set<String> compIdList = new HashSet<String>();
for (final SObject acct : compSet)
{
compIdList.add(acct.getId());
} // for
return Util.twoSetsMatch(compIdList, idList);
} // matches
}
但是,当我尝试在我的 JUnit 测试中进行设置时……
final Set<Account> firstBatch = new HashSet<Account>();
firstBatch.add(acct);
final SObject[] firstBatchAccts = Matchers.argThat(new AccountMatcher(firstBatch));
Mockito.verify(mockConnection, Mockito.times(1)).update(firstBatchAccts);
当我 运行 它时,我得到以下异常……
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Misplaced argument matcher detected here:
-> at org.mainco.subco.sf.repo.AccountDaoIT.testUpdateAccountMaxRowsReached(AccountDaoIT.java:129)
You cannot use argument matchers outside of verification or stubbing.
Examples of correct usage of argument matchers:
when(mock.get(anyInt())).thenReturn(null);
doThrow(new RuntimeException()).when(mock).someVoidMethod(anyObject());
verify(mock).someMethod(contains("foo"))
Also, this error might show up because you use argument matchers with methods that cannot be mocked.
Following methods *cannot* be stubbed/verified: final/private/equals()/hashCode().
Mocking methods declared on non-public parent classes is not supported.
at org.mainco.subco.sf.repo.AccountDaoIT.testUpdateAccountMaxRowsReached(AccountDaoIT.java:130)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.junit.runners.model.FrameworkMethod.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88)
at org.junit.runners.ParentRunner.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access[=14=]0(ParentRunner.java:58)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
这是因为您已经将 firstBatchAccts
(Matcher 调用的结果)提取到一个变量,而不是一个方法。 argThat
和所有其他 Mockito 匹配器 work via side-effects,因此必须在正确的时间调用它们。
verify
检查一个空的匹配器堆栈,然后重置模拟的期望,这样它们就不会干扰验证。发生了一些匹配器调用,然后对要验证的方法的调用完成了该过程:它清除堆栈,检查发生的方法调用,并将模拟切换回存根行为(如果有)。
按照你的方式,argThat
被调用,然后调用 verify
,verify
检查没有发生未使用的 Matcher 调用。这会触发您的异常。
改为内联调用:
verify(mockConnection).update(argThat(new AccountMatcher(firstBatch)));
...或者将其改为方法调用,以保持顺序正确:
public SObject[] arrayMatchingAccounts(Set<Account> accountSet) {
return argThat(new AccountMatcher(accountSet));
}
verify(mockConnection).update(arrayMatchingAccounts(firstBatch));
我正在使用 Mockito 1.10.18。我正在尝试为具有以下签名的方法创建自定义参数匹配器……
SaveResult[] com.sforce.soap.enterprise.EnterpriseConnection.update(SObject[] sObjects) throws ConnectionException
我编写了以下自定义参数匹配器……
class AccountMatcher extends ArgumentMatcher<SObject[]>
{
private Set<String> idList = new HashSet<String>();
AccountMatcher(final Set<Account> mainList)
{
for (final Account acct : mainList)
{
idList.add(acct.getId());
} // for
}
public boolean matches(Object param)
{
final SObject[] compSet = ((SObject[]) param);
final Set<String> compIdList = new HashSet<String>();
for (final SObject acct : compSet)
{
compIdList.add(acct.getId());
} // for
return Util.twoSetsMatch(compIdList, idList);
} // matches
}
但是,当我尝试在我的 JUnit 测试中进行设置时……
final Set<Account> firstBatch = new HashSet<Account>();
firstBatch.add(acct);
final SObject[] firstBatchAccts = Matchers.argThat(new AccountMatcher(firstBatch));
Mockito.verify(mockConnection, Mockito.times(1)).update(firstBatchAccts);
当我 运行 它时,我得到以下异常……
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Misplaced argument matcher detected here:
-> at org.mainco.subco.sf.repo.AccountDaoIT.testUpdateAccountMaxRowsReached(AccountDaoIT.java:129)
You cannot use argument matchers outside of verification or stubbing.
Examples of correct usage of argument matchers:
when(mock.get(anyInt())).thenReturn(null);
doThrow(new RuntimeException()).when(mock).someVoidMethod(anyObject());
verify(mock).someMethod(contains("foo"))
Also, this error might show up because you use argument matchers with methods that cannot be mocked.
Following methods *cannot* be stubbed/verified: final/private/equals()/hashCode().
Mocking methods declared on non-public parent classes is not supported.
at org.mainco.subco.sf.repo.AccountDaoIT.testUpdateAccountMaxRowsReached(AccountDaoIT.java:130)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.junit.runners.model.FrameworkMethod.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88)
at org.junit.runners.ParentRunner.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access[=14=]0(ParentRunner.java:58)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
这是因为您已经将 firstBatchAccts
(Matcher 调用的结果)提取到一个变量,而不是一个方法。 argThat
和所有其他 Mockito 匹配器 work via side-effects,因此必须在正确的时间调用它们。
verify
检查一个空的匹配器堆栈,然后重置模拟的期望,这样它们就不会干扰验证。发生了一些匹配器调用,然后对要验证的方法的调用完成了该过程:它清除堆栈,检查发生的方法调用,并将模拟切换回存根行为(如果有)。
按照你的方式,argThat
被调用,然后调用 verify
,verify
检查没有发生未使用的 Matcher 调用。这会触发您的异常。
改为内联调用:
verify(mockConnection).update(argThat(new AccountMatcher(firstBatch)));
...或者将其改为方法调用,以保持顺序正确:
public SObject[] arrayMatchingAccounts(Set<Account> accountSet) {
return argThat(new AccountMatcher(accountSet));
}
verify(mockConnection).update(arrayMatchingAccounts(firstBatch));