使用powerMockito的JUnit测试给出了NPE

使用powerMockito的JUnit测试给出了NPE,junit,mockito,powermockito,Junit,Mockito,Powermockito,我有一个类,我想为它编写一个Junit单元测试用例 public class ComparatorUtil { public static Map<String, ValueDifference<Object>> compareJsonObject(Object srcObject, Object targetObject) throws JsonGenerationException, JsonMappingException,

我有一个类,我想为它编写一个Junit单元测试用例

public class ComparatorUtil {

    public static Map<String, ValueDifference<Object>> compareJsonObject(Object srcObject, Object targetObject)
                throws JsonGenerationException, JsonMappingException, IOException {
        String initialJson = ConverterUtil.convertObjectToJson(srcObject);
        String updatedJson = ConverterUtil.convertObjectToJson(targetObject);
        Gson g = new Gson();
        Type mapType = new TypeToken<Map<String, Object>>(){}.getType();
        Map<String, Object> firstMap = g.fromJson(initialJson, mapType);
        Map<String, Object> secondMap = g.fromJson(updatedJson, mapType);
        Map<String, MapDifference.ValueDifference<Object>> diffMap = Maps.difference(firstMap, secondMap).entriesDiffering();
        return diffMap;
    }
}


public class ConverterUtil {

    public static String convertObjectToJson(Object o)
            throws JsonGenerationException, JsonMappingException, IOException {
        ObjectMapper mapperObj = new ObjectMapper();
        return mapperObj.writeValueAsString(o);
    }
}

当我运行测试类时,由于
initialJson
updatedJson
即将为Null,我得到了一个
Null指针异常。谁能告诉我哪里做错了

这里有太多的错误

  • 您似乎假设了如何使用PowerMock。但是你把它们放在一起根本没有意义!例如,您需要使用'when().thenReturn()'创建模拟规范
  • 意思:仅仅指示PowerMock对某个类进行模拟是不够的。当调用这些静态方法时,您必须告诉PowerMock要返回的实际值
  • 因此,从自上而下阅读一篇好的教程开始。不要在自己的代码中使用PowerMock,而是看看教程如何解决一个简单的问题
然后:PowerMock以一定的成本出现。所以你要避免使用它。相反,您应该后退一步,重新编写代码,以便在不需要模拟静态方法的情况下对其进行测试。你看,我们讨论的是将一些输入转换成一些输出的代码。在这种情况下,您应该能够编写完全不需要模拟的生产和测试代码。如果有的话,您应该使用Mockito之类的框架——好的生产代码可以在没有PowerMock的情况下进行测试

更具体地说:为什么需要模拟静态方法?这似乎表明ObjectMapper在单元测试设置中不起作用。就从那里开始

您知道,转换方法的良好单元测试应该如下所示:

assertThat(someConverterUnderTest.convert(fineTunedInput), is(expectedOutput));
就这样!您应该将转换器设计为在单元测试环境中完全工作。然后所有对模拟的需求都消失了。换句话说:您当前正在测试实现细节。相反,您应该始终尝试测试方法的公共契约。测试实现细节有时是不可避免的,但正如前面所写的:您在这里展示的代码实际上应该在没有模拟的情况下进行测试


然后:即使您需要模拟:静态方法也会妨碍您。这是一个明确的信号,你不应该在这里使用静态!相反,您可以将那些可能需要模拟的元素转换为被测试类的参数或字段。因为这样您就可以简单地注入模拟对象。这意味着您不再需要PowerMock(ito)工具。

我已经为ConverterUtil.java类编写了单元测试用例。。那么我需要再次测试ConverterUtil.convertObjectToJson(obj)返回的值吗??我相信没有。我在这里尝试测试的是,如果调用了ComparatorUtil.compareJsonObject(srcObject,targetObject)方法,那么就调用ConverterUtil.convertObjectToJson(srcObject)方法应该被调用两次…请告诉我您是否有更好的方法为此场景编写junit测试用例??是的,我还将编写一个测试用例来断言compareJsonObject()方法返回的值。我更新了答案。。。即使你不想接受这个答案(尽管10年的经验告诉我这是正确的答案),但至少要考虑一下,我把精力投入到你需要的信息中。@ GhostCat:谢谢你的帮助。我对你的答案投了更高的票,不确定它是否会公开反映,因为我没有太多的观点。。。如前所述:您也可以使用PowerMock。但为了确切地告诉您代码不起作用的原因,我们需要一个真实的答案。
assertThat(someConverterUnderTest.convert(fineTunedInput), is(expectedOutput));