[英]Mockito NumberFormat mocking NullPointer in when() method
所以我有这段代码会抛出一个NullPointerException
NumberFormat formatterFake = mock(NumberFormat.class);
when(formatterFake.format(1)).thenReturn("1");
问题是我在when()方法中得到一个异常:
java.lang.NullPointerException
at java.text.NumberFormat.format(NumberFormat.java:297)
我也试图模仿具体课程,给我相同的结果。
NumberFormat formatterFake = mock(DecimalFormat.class);
我对Mockito有点新意,任何帮助都会非常谨慎。 提前致谢。
好的,所以你在这里做的一切都是为了在mock上存根方法。
NumberFormat
是一个抽象类。 这通常很好,因为Mockito可以像普通类一样模拟抽象类。 问题与NumberFormat#format(long)
方法的实现有关。
看一下我使用Oracle jdk 1.7.0 update 2的实现的源代码,你可以看到这个方法的作用:
public final String format(long number) {
return format(number, new StringBuffer(), DontCareFieldPosition.INSTANCE).toString();
}
您正在模拟的格式方法实际上是调用另一种格式方法: NumberFormat#format(long, StringBuffer, FieldPosition)
,它位于同一个抽象类中。 然后它返回调用toString()
的结果,调用该调用的结果。 这是一个FINAL方法,Mockito不能存根。
当您使用when-then语法来存根方法时,Mockito实际上会调用您正在存根的方法(如果它有最终实现)。 所以当你写:
when(formatterFake.format(1))
实际上,您正在调用抽象NumberFormat
类中实现的format
方法的第一次重载。
format
的第一次重载的最终实现调用第二种format
方法。 第二种format
是 NumberFormat
的抽象方法 。 所以没有实现调用。
没问题,我们正在使用模拟器。 Mockito为模拟中的每个未实现方法提供默认存根。 默认情况下,对于返回值的所有方法,mock返回null,空集合或适当的原始/原始包装器值(例如:0,false,...表示int / Integer,boolean / Boolean,...)。
所以当试图将调用存根到NumberFormat#format(long)
,因为它有一个实现,你最终会调用NumberFormat#format(long, StringBuffer, FieldPosition)
的默认存根,返回null
,然后是.toString()
-ed你有原因你的NPE。
通常你会模拟一个接口,而不是直接模拟一个类,这将完全避免这类问题的可能性,因为没有最终的任何事情。 但是,由于此处没有可用于模拟的接口,因此不能选择。
你可以直接模拟3-arg格式的重载:它应该允许你根据需要调用格式的一个参数版本:
@Test
public void test() {
final NumberFormat mockFormatter = mock(NumberFormat.class);
final StringBuffer buffer = new StringBuffer("1");
when(mockFormatter.format(anyLong(), any(StringBuffer.class), any(FieldPosition.class))).thenReturn(buffer);
System.out.println("Result: " + mockFormatter.format(1));
}
但是,我不确定这是最好的解决方案。 也许其他人会权衡。
编辑:
在看到Garrett Hall的回答后,我更明确地说,当我谈论实现时,我的意思是最终实现。
正如他所建议的那样,如果你愿意走这条路,PowerMock会允许直接嘲笑最终的格式方法。
您需要使用PowerMock来模拟最终方法。
我不确定为什么你需要在NumberFormat
类上模拟最终方法,这是一种测试气味。 请发布您的测试。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.