java 当我的第一个方法参数是 String 类型时,如何使用 Powermock 的 Whitebox.invokeMethod(Object instance, Object... arguments)?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32768430/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 20:44:23  来源:igfitidea点击:

How do I use Powermock's Whitebox.invokeMethod(Object instance, Object... arguments) when my first method parameter is String type?

javaunit-testingjunitpowermockwhite-box

提问by pluralMonad

I would like to not explicitly name the method I am invoking in the invokeMethod()arguments. Powermock offers an overloaded invokeMethod()that infers the method based on the parameters passed.

我不想在invokeMethod()参数中明确命名我正在调用的方法。Powermock 提供了一个重载invokeMethod(),它根据传递的参数推断方法。

invokeMethod(Object instance, Object... arguments)

The problem I am running into is that my first parameter is of type String. This invokes the invokeMethod()with the signature,

我遇到的问题是我的第一个参数的类型是String。这将调用invokeMethod()带有签名的

invokeMethod(Object instance, String methodToExecute, Object... arguments)

Here is a model of the test...

这是测试的模型...

@Test
public void thisIsATest() throws Exception{
    TheClassBeingTested myClassInstance = new TheClassBeingTested();
    String expected = "60";
    String firstArgument = "123A48"; 

    ReturnType returnedTypeValue = Whitebox.invokeMethod(myClassInstance, firstArgument, AnEnum.TypeA);
    String actual = returnedTypeValue.getTestedField();
    assertEquals("Expected should be actual when AnEnum is TypeA", expected, actual);
}

This gives me the error,

这给了我错误,

org.powermock.reflect.exceptions.MethodNotFoundException: No method found with name '123A48' with parameter types: [ AnEnum ] in class TheClassBeingTested.`

I got it to work by changing the first parameter's type to Object, but this feels dirty to me.

我通过将第一个参数的类型更改为 来使其工作Object,但这对我来说感觉很脏。

@Test
public void thisIsATest() throws Exception{
    TheClassBeingTested myClassInstance = new TheClassBeingTested();
    String expected = "60";
    Object firstArgument = "123A48"; 

    ReturnType returnedTypeValue = Whitebox.invokeMethod(myClassInstance, firstArgument, AnEnum.TypeA);
    String actual = returnedTypeValue.getTestedField();
    assertEquals("Expected should be actual when AnEnum is TypeA", expected, actual);
}

Is there a correct way to pass a Stringtype as the first argument while not hard coding my method name into the invokeMethod()call? I have found nothing in the Powermock documentation or forums addressing this, but it certainly cannot be all that uncommon.

是否有正确的方法将String类型作为第一个参数传递,同时不将我的方法名称硬编码到invokeMethod()调用中?我在 Powermock 文档或论坛中没有找到任何内容来解决这个问题,但它肯定不会那么罕见。

回答by dfashimpaur

What you really need to do is look at TheClassBeingTested.java. The error message is telling you that the problem is that Whitebox.invoke method cannot find a method named "123A48" in TheClassBeingTested it is creating by reflection. In this case, the invokeMethod I think you have chosen is looking for parameters (Object classUnderTest, String methodName, Object...parameters).

您真正需要做的是查看 TheClassBeingTested.java。错误消息告诉您问题在于 Whitebox.invoke 方法在通过反射创建的 TheClassBeingTested 中找不到名为“123A48”的方法。在这种情况下,我认为您选择的 invokeMethod 正在寻找参数(Object classUnderTest、String methodName、Object...parameters)。

Try something like this:

尝试这样的事情:

public class TheClassBeingTested {
    private String foo;

    public void setFoo(String fooValue) {
        foo = fooValue;
    }

    public String getFoo() {
        return foo;
    }

}

Then you can test with Whitebox like this:

然后你可以像这样用 Whitebox 进行测试:

public class TheClassBeingTestedTester {

    @Test
    public void thisIsATest() throws Exception {
        TheClassBeingTested toBeTested = new TheClassBeingTested();
        String theMethodToTest = "setFoo";
        String expectedFooValue = "foo bar baz";

        ReturnType returnedTypeValue = Whitebox.invokeMethod(toBeTested, theMethodToTest, expectedFooValue);
        String actual = returnedTypeValue.getTestedField();
        assertEquals("Expected " + expected + " but found " + actual, expected, actual);
     }
}

Hope that helps.

希望有帮助。

... edited response below

...在下面编辑回复

As I failed to read your question carefully while also working on other development, I missed the point.

由于我在进行其他开发时没有仔细阅读您的问题,因此我没有抓住重点。

In this case, I would make the following modification to your test to avoid the invoke method ambiguity issue:

在这种情况下,我将对您的测试进行以下修改以避免 invoke 方法歧义问题:

@Test
public void thisIsATest() throws Exception{
    TheClassBeingTested myClassInstance = new TheClassBeingTested();
    String expected = "60";

    Object[] parameters = new Object[]{"123A48", AnEnum.TypeA};

    ReturnType returnedTypeValue = Whitebox.invokeMethod(myClassInstance, parameters);

    String actual = returnedTypeValue.getTestedField();
    assertEquals("Expected should be actual when AnEnum is TypeA", expected, actual);

}

}

This way, the ambiguity is removed so that the invokeMethod(Object instance, Object... arguments) will only see the array of objects which is what the method signature tells the compiler to expect. Even though String is an Object, in the method signature reflection, java.lang.reflect defers to the second signature which it feels you are trying to tell it to use over the one you want it to use.

这样,歧义被消除,以便 invokeMethod(Object instance, Object... arguments) 只会看到对象数组,这是方法签名告诉编译器所期望的。即使 String 是一个对象,在方法签名反射中, java.lang.reflect 遵循第二个签名,它感觉您正试图告诉它使用您希望它使用的签名。

Hope this answer meets your request better.

希望这个答案更好地满足您的要求。