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

时间:2017-09-14 07:04:42

标签: java unit-testing mocking mockito powermock

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

这是我的源代码:

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

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

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

如何使用API​​ PowerMockito.verifyPrivate()确认私有方法的通话时间;

1 个答案:

答案 0 :(得分:1)

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

  1. 使用@PrepareForTest将枚举常量设置为fullyQualifiedNames,例如`@PrepareForTest(values = {ConversionCommon.class,LengthConversion.class},fullyQualifiedNames =“com.somepackage.ConversionCommon $ INSTANCE”)
  2. 例如创建一个间谍:PowerMockito.spy(ConversionCommon.INSTANCE)
  3. 用间谍替换常量:Whitebox.setInternalState(ConversionCommon.class, spy)
  4. 现在,您可以像往常一样存根间谍方法doNothing().when(spy, "setUnitCount");
  5. 通过枚举的一些抽象单例实现的代码片段:

    枚举

    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