2

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

invokeMethod(Object instance, Object... arguments)

我遇到的问题是我的第一个参数是String. 这会调用invokeMethod()带有签名的

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

这是一个测试模型...

@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);
}

这给了我错误,

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

我通过将第一个参数的类型更改为 来让它工作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);
}

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

4

1 回答 1

3

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

尝试这样的事情:

public class TheClassBeingTested {
    private String foo;

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

    public String getFoo() {
        return foo;
    }

}

然后你可以像这样使用 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);
     }
}

希望有帮助。

...在下面编辑了回复

由于我在进行其他开发的同时没有仔细阅读您的问题,所以我错过了重点。

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

@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);

}

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

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

于 2015-09-24T20:04:47.610 回答