当尝试创建自定义参数匹配器时,invaliduseofmatchersexception异常



我使用的是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$1.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$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.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匹配器都是通过副作用工作的,所以它们必须在正确的时间被调用。

verify检查匹配器的空堆栈,然后重置模拟上的期望,这样它们就不会干扰验证。发生了一些匹配器调用,然后对要验证的方法的调用完成了该过程:它清除堆栈,检查发生的方法调用,并将模拟切换回存根行为(如果有的话)。

你有它的方式,argThat被调用,然后调用verify发生,verify检查没有未使用的匹配器调用发生。这会触发异常。

而是内联调用:

verify(mockConnection).update(argThat(new AccountMatcher(firstBatch)));

…或者将其改为方法调用,这样可以保持顺序正确:

public SObject[] arrayMatchingAccounts(Set<Account> accountSet) {
  return argThat(new AccountMatcher(accountSet));
}
verify(mockConnection).update(arrayMatchingAccounts(firstBatch));

相关内容

  • 没有找到相关文章

最新更新