我正在使用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(匹配器调用的结果)提取到变量而不是方法中。 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));

关于java - 尝试创建自定义参数匹配器时,org.mockito.exceptions.misusing.InvalidUseOfMatchersException,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32101820/

10-13 04:29