java - 如果方法在使用 Powermock 进行单元测试期间调用,如何有效验证方法

标签 java unit-testing mocking mockito powermock

当我使用 Powermock 模拟一个私有(private)方法,然后在另一个方法的单元测试中验证它时,检查它是否被调用以及调用时间是否正确。但是我发现我可以验证该方法是否被调用并且使用正确的参数,该方法的调用次数可以是任意数字,但是单元测试总是通过。如果有人可以帮我解决问题。谢谢!

这是我的源代码:

public enum ConversionCommon{
INSTANCE;

...

public void getConvertTypeData(JSONObject result, JSONObject conversionData, String intent){
    String uncertainty = "";
    String unit1 = "";
    String unit1_char = "";
    if(result.has(ConversionDefine.CONVERSION_UNCERTAINTY)){
        uncertainty = result.getString(ConversionDefine.CONVERSION_UNCERTAINTY);
    }
    if(result.has(ConversionDefine.CONVERSION_UNIT1)){
        unit1 = result.getString(ConversionDefine.CONVERSION_UNIT1);
    }
    if(result.has(ConversionDefine.CONVERSION_UNIT1_CHAR)){
        unit1_char = result.getString(ConversionDefine.CONVERSION_UNIT1_CHAR);
    }

    setUnitCount(conversionData, uncertainty, intent);
    setDestUnits(conversionData, unit1, unit1_char);

}

getConvertTypeData() 方法一次调用两个方法。以下是我的测试用例代码:

@RunWith(PowerMockRunner.class)
@PrepareForTest({ ConversionCommon.class, LengthConversion.class })
@PowerMockIgnore("javax.management.*")

public class ConversionCommonTest{

@Before
public void setUp() throws Exception{
    PowerMockito.mockStatic(LengthConversion.class);//
    PowerMockito.spy(LengthConversion.class); //
}

@Test
public void should_getConvertTypeData_invoke_setUnitCount() throws Exception{
    JSONObject result = new JSONObject();
    JSONObject conversionData = new JSONObject();
    result.put(ConversionDefine.CONVERSION_UNCERTAINTY, "3");
    result.put(ConversionDefine.CONVERSION_UNIT1, "meter");
    result.put(ConversionDefine.CONVERSION_UNIT1_CHAR, "centmeter");

    suppress(method(ConversionCommon.class, "setUnitCount", JSONObject.class, String.class, String.class));
    ConversionCommon.INSTANCE.getConvertTypeData(result, conversionData, ConversionDefine.INTENT_LENGTH_CONVERSION);
    PowerMockito.verifyPrivate(ConversionCommon.INSTANCE, Mockito.times(1)).invoke("setUnitCount", Mockito.anyObject(), Mockito.anyString(), Mockito.anyString());
}

测试用例可以成功运行,但是如果我将最后一行更改为...

PowerMockito.verifyPrivate(ConversionCommon.INSTANCE, Mockito.times(100)).invoke("setUnitCount", Mockito.anyObject(), Mockito.anyString(), Mockito.anyString());

... 并重新运行测试用例。结果也通过了。但实际上我只在Refo中调用了方法setUnitCount一次。

测试框架版本:mockito:1.10.19;powermock:1.6.5

如何使用 API PowerMockito.verifyPrivate() 更正验证私有(private)方法的调用时间;

最佳答案

除了一件事,你做对了。你在监视枚举常量。每个枚举常量都是单独的内部类。所以你必须添加两件事:

  1. 使用 fullyQualifiedNames@PrepareForTest 枚举常量,例如`@PrepareForTest(values = { ConversionCommon.class, LengthConversion.class }, fullyQualifiedNames = "com.somepackage. ConversionCommon$INSTANCE")
  2. 创建一个 spy ,例如:PowerMockito.spy(ConversionCommon.INSTANCE)
  3. 用 spy 替换常量:Whitebox.setInternalState(ConversionCommon.class, spy)
  4. 现在,您可以像往常一样对 spy 方法进行 stub doNothing().when(spy, "setUnitCount");

通过枚举实现一些抽象单例的代码片段:

枚举

public enum Singleton {

    INSTANCE;

    public void doSomething(){
        callPrivateMethod();
    }

    private void callPrivateMethod() {

    }
}

测试

RunWith(PowerMockRunner.class)
@PrepareForTest(value = Singleton.class, fullyQualifiedNames = "com.stackoverflow.q46212600.Singleton$INSTANCE")
public class ClassUseSingletonTest {

    @Test
    public void should_verify_enum_method() throws Exception {
        final Singleton spy = PowerMockito.spy(Singleton.INSTANCE);
        Whitebox.setInternalState(Singleton.class, spy);

        doNothing().when(spy, "callPrivateMethod");

        new ClassUseSingletone().doSomething("do");

        PowerMockito.verifyPrivate(Singleton.INSTANCE, times(1)).invoke("callPrivateMethod");

    }

}

完整示例,您可能会找到 here

关于java - 如果方法在使用 Powermock 进行单元测试期间调用,如何有效验证方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46212600/

相关文章:

java - 在 JUnit 测试中抛出所有异常是不好的做法吗?

c# - 是否值得为调用其他方法的方法编写测试,这些方法 100% 被单个单元测试覆盖?

c# - 如何在 Moq 中模拟链式 Linq 方法

java - 为什么我不能在我的 super() 调用周围使用 try block ?

java - NoClassDefFound 乔格

java - OOP:一个类可以描述另一个实体的属性

java - 空指针异常取决于 Mockito 中的语句链接?

java - 如何断言抛出异常后尚未调用方法?

java - 在 Linux 中如何通过脚本检查安装了哪个版本的 Java?

java,获取设置方法