当前位置: 首页 > 知识库问答 >
问题:

打电话给莫基托。以编程方式验证

夹谷成仁
2023-03-14

我有一个较大的代码库,包含许多装饰器类,它们通常将除一个方法外的所有方法委托给一个委托对象,例如:

class WrapperThing implements Thing{
   private final Thing delegate;
   WrapperThing(Thing thing){this.delegate=thing;}

   public boolean method1(){ return delegate.method1(); }
   public String method2(int arg1, boolean arg2){ return delegate.method2(arg1, arg2); }
   // lots more methods here, all delegating to delegate
}

现在,我正在使用Junit 5@TestFactory为这些包装创建单元测试,调用WrapperThing上的每个方法,并希望验证包装委托上是否有调用,这是一个Mockito mock。

以下是我目前的代码

private void testMethodDelegation(final Method method) {
    D delegate = mock(delegateType);
    W wrapper = createWrapper(delegate);

    List<Object> args = new ArrayList<>(method.getParameterTypes().length + 1);
    args.add(wrapper);
    gatherMethodArgs(method, args); // populate args with mocks or default values
    try {
        method.invoke(args.toArray(new Object[0]));
    }catch(Exception e) {
        // this is fine, we're just testing the delegation
    }

    // now comes the verify part
    List<Object> mockArgs = new ArrayList<>();
    try {
        mockArgs.add(verify(delegate));
        mockArgs.addAll(nCopies(args.size()-1, any()));
        method.invoke(mockArgs.toArray(new Object[0]));
    }catch (Exception e) {
        throw new IllegalStateException(e);
    }

}

当我运行这个,我得到的错误是:

org.mockito.exceptions.misusing.InvalidUseOfMatchersException: 
Misplaced or misused argument matcher detected here:

-> at some.packagename.AbstractDelegateTest.testMethodDelegation(AbstractDelegateTest.java:81)

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"))

我是否做错了什么,或者如果您不知道确切的方法,是否无法验证方法调用?

共有1个答案

穆招
2023-03-14

问题是我在调用方法。调用()错误。我认为格式是方法。调用([target,arg1,…argn]),但它实际上是方法。调用(目标[arg1,…argn])。这是漫长的一天,我的坏朋友。

此代码的工作原理

private void testMethodDelegation(final Method method) {
    D delegate = mock(delegateType);
    W wrapper = createWrapper(delegate);

    List<Object> args = new ArrayList<>(method.getParameterTypes().length);
    gatherMethodArgs(method, args); // populate args with mocks or default values
    try {
        method.invoke(wrapper, args.toArray(new Object[0]));
    } catch (Exception e) {
        // this is fine, we're just testing the delegation
        throw new IllegalStateException(e);
    }
    callVerify(method, delegate);
}

private void callVerify(final Method method, final D delegate) {
    // now comes the verify part
    List<Object> mockArgs = new ArrayList<>(method.getParameterTypes().length);
    try {
        D verifyDelegate = verify(delegate);
        gatherVerifyArgs(method, mockArgs);
        method.invoke(verifyDelegate, mockArgs.toArray(new Object[0]));
    } catch (Exception e) {
        throw new IllegalStateException(e);
    }
}

private void gatherVerifyArgs(final Method method, final List<Object> args) {
    for (Class<?> parameterType : method.getParameterTypes()) {
        if (int.class == parameterType) {
            args.add(anyInt());
        } else if (boolean.class == parameterType) {
            args.add(anyBoolean());
        } else if (long.class == parameterType) {
            args.add(anyLong());
        } else if (double.class == parameterType) {
            args.add(anyDouble());
        } else if (float.class == parameterType) {
            args.add(anyFloat());
        } else if (String.class == parameterType) {
            args.add(anyString());
        } else {
            args.add(any());
        }
    }
}

private void gatherMethodArgs(final Method method, final List<Object> args) {

    int i = 0;
    for (Class<?> type : method.getParameterTypes()) {
        try {
            if (type == String.class) {
                args.add("");
            } else if (type.isArray()) {
                args.add(Array.newInstance(type.getComponentType(), 0));
            } else if (Primitives.allPrimitiveTypes().contains(type)) {
                args.add(Defaults.defaultValue(type));
            } else if (Primitives.allWrapperTypes().contains(type)) {
                args.add(Defaults.defaultValue(Primitives.unwrap(type)));
            } else if (type == List.class) {
                args.add(ImmutableList.of());
            } else if (type == Set.class) {
                args.add(ImmutableSet.of());
            } else if (type == Map.class) {
                args.add(ImmutableMap.of());
            } else if (type.getName().startsWith("java.util.")) {
                args.add(type.newInstance());
            } else {
                args.add(mock(type));
            }
        } catch (Exception e) {
            throw new IllegalStateException(
                String.format("Error mocking parameter %d (%s) of method %s", i,
                              method.getGenericParameterTypes()[i], method), e);
        }
        i++;
    }
}
 类似资料:
  • 我找到了使用ReflectionUtils的方法 现在我想驱动这个方法返回一个指定的值。通常,如果< code>myMethod是公共的,我会写例如 但是有没有可能用私有的myMethod来实现呢?< br >当我打电话时 我有Java . lang . reflect . invocationtargetexception .我读过关于PowerMock的文章,但是我想知道是否只有Mockito

  • 我对莫基托有疑问。我想测试这个简单的类: 我写了这个简单的测试: 此测试运行时没有错误。我等待它没有编译,因为没有任何对userService方法的调用…

  • Mockito似乎是一个非常好的Java存根/模拟框架。唯一的问题是我找不到任何关于使用API的最佳方法的具体文档。测试中使用的常用方法包括: 当您在实践中看到Mockito的示例时,您会看到如下代码: 从我读过的所有文档中,我已经识别了几个Mockito“语法”的“模式”,这些“语法”是通过将这些方法调用像上面的示例一样链接在一起而获得的。我发现的一些常见模式有: 当/然后:当(你的方法())。

  • Mockito——我知道间谍在对象上调用实际方法,而模拟在双对象上调用方法。此外,除非有代码气味,否则要避免间谍。然而,间谍是如何工作的?我应该在什么时候使用他们?它们与模拟有什么不同?

  • 问题内容: 是否可以以编程方式在android中接听电话? 我找到了一些不可能的地方,但随后安装了应用https://play.google.com/store/apps/details?id=com.a0softus.autoanswer可以 正常工作。 我已经搜索了很多并尝试了很多方法,而且呼叫拒绝功能正常,但呼叫应答功能却无效。 我尝试了以下代码进行电话应答,如下所示: 函数拒绝调用可以正常

  • 我正在尝试为具有特定扩展名的文件在“打开”菜单中添加eclipse编辑器。我在org.eclipse.ui.editors扩展点中使用launcher实现了这一点,在launcher中我使用了“open editor”方法,它需要传递编辑器ID。有没有什么方法可以让我们以编程方式打开一个编辑器,而不需要传递编辑器ID呢?我们可以通过传递实现编辑器的类的实例以编程方式打开编辑器吗?..