4

我想为我的课程编写单元测试。这个类有一个公共方法,在公共方法内部有对同一个类的私有方法的调用。我想模拟对那些私有方法的调用。该类与此类似:

public class SomeClass {
    public int somePublicMethod(int num) {
        int num2 = somePrivateMethod1(num);
        int num3 = somePrivateMethod2(num);

        return num2 + num3;
    }

    private int somePrivateMethod1(int num) {
        return 2*num;
    }

    private int somePrivateMethod2(int num) {
        return 3*num;
    }
}

对于我的单元测试,我正在尝试将 PowerMock 与 Mockito 和 TestNG 一起使用。这是我在测试 somePublicMethod 的测试中的尝试:

import static org.powermock.api.mockito.PowerMockito.doReturn;
import static org.powermock.api.mockito.PowerMockito.spy;

import org.powermock.core.classloader.annotations.PrepareForTest;
import org.testng.Assert;
import org.testng.annotations.Test;

@PrepareForTest(SomeClass.class)
public class SomeClassTest {

    @Test
    public void testSomePublicMethod() throws Exception {
        int num = 4;        

        SomeClass someClassSpy = spy(new SomeClass());

        doReturn(8).when(someClassSpy, "somePrivateMethod1", num);
        doReturn(12).when(someClassSpy, "somePrivateMethod2", num);

        int result = someClassSpy.somePublicMethod(num);

        Assert.assertEquals(result, 20);
    }
}

当我运行这个测试时,我得到一个异常和一些提示:

FAILED: testSomePublicMethod
org.mockito.exceptions.misusing.UnfinishedStubbingException: 
Unfinished stubbing detected here:
-> at org.powermock.api.mockito.internal.PowerMockitoCore.doAnswer(PowerMockitoCore.java:31)

E.g. thenReturn() may be missing.
Examples of correct stubbing:
    when(mock.isOk()).thenReturn(true);
    when(mock.isOk()).thenThrow(exception);
    doThrow(exception).when(mock).someVoidMethod();
Hints:
 1. missing thenReturn()
 2. you are trying to stub a final method, you naughty developer!

我在网上查看了一些示例,但我没有找到一个专门使用 PowerMock 和 Mockito 和 TestNG 来做我想做的事。有人可以给我一些关于我可以做些什么不同的指示吗?

4

3 回答 3

5

我不认为这是 PowerMock 的问题。看起来它应该可以正常工作。我想知道 TestNG 与 PowerMock 交互是否有问题?

我没有使用 TestNG 的经验,所以我尝试在 JUnit 中运行该类。 SomeClass保持原样,SomeClassTest进行了最低限度的修改以使用 JUnit:

import static org.powermock.api.mockito.PowerMockito.*;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
@PrepareForTest(SomeClass.class)
public class SomeClassTest {

    @Test
    public void testSomePublicMethod() throws Exception {
        final int num = 4;

        final SomeClass someClassSpy = spy(new SomeClass());

        doReturn(8).when(someClassSpy, "somePrivateMethod1", num);
        doReturn(12).when(someClassSpy, "somePrivateMethod2", num);

        final int result = someClassSpy.somePublicMethod(num);

        Assert.assertEquals(result, 20);
    }
}

测试通过。

您是否需要像 JUnit 一样指定PowerMockRunner.classusing@RunWIth或类似的注解?如果我删除该注释,我会收到您发布的相同错误消息。

编辑:

根据此链接: http ://code.google.com/p/powermock/wiki/TestNG_usage

您需要告诉 TestNG 使用 PowerMock 对象工厂。要以编程方式执行此操作,请将这样的方法添加到您的测试类中:

@ObjectFactory
public IObjectFactory getObjectFactory() {
    return new org.powermock.modules.testng.PowerMockObjectFactory();
}

或者为了安全起见,您还可以从 PowerMockTestCase 扩展:

@PrepareForTest(SomeClass.class)
public class SomeClassTest extends PowerMockTestCase {
   //...
}
于 2012-05-11T12:34:58.660 回答
1

你不能那样做。您是否尝试使用反射?

通过使用反射,您可以通过模拟调用方法来模拟私有方法,或者更简单:您可以将其更改为临时公共,然后在测试之后(可能在拆解中) - 您可以将其更改回私有。

希望这有帮助。

于 2012-05-10T09:38:16.457 回答
0

我认为你在这里达到了 Mockito 限制。在类似的情况下,我使用 Powermock 方法替换,或者,将目标方法声明为受保护并在构造测试类实例时覆盖它。希望有帮助。

于 2012-05-10T09:33:28.090 回答