所以我得到了这段抛出 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 上 stub 方法。
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)
,它位于同一个抽象类中。然后返回对 that 调用结果调用 toString()
的结果。这是一个 FINAL 方法,Mockito 不能 stub 。
当您使用 when-then 语法对方法进行 stub 时,Mockito 实际上会调用您 stub 的方法(如果它有最终实现)。所以当你写:
when(formatterFake.format(1))
您实际上是在调用在抽象 NumberFormat
类中实现的 format
方法的第一个重载。
format
的第一个重载的最终实现调用了第二个format
方法。第二种 format
是 NumberFormat
中的抽象方法。所以没有可调用的实现。
没问题,我们正在使用模拟。 Mockito 为模拟中的每个未实现的方法提供默认 stub 。 By default, for all methods that return value, mock returns null, an empty collection or appropriate primitive/primitive wrapper value (e.g: 0, false, ... for int/Integer, boolean/Boolean, ...).
因此,当尝试对 NumberFormat#format(long)
调用 stub 时,因为它有一个实现,所以您最终会调用 NumberFormat#format(long, StringBuffer, FieldPosition)
返回 null
,然后被 .toString()
编辑,这就是 NPE 的原因。
解决方案
通常你会模拟一个接口(interface),而不是直接模拟一个类,这将完全避免这类问题的可能性,因为没有最终的东西。但是,由于此处没有可用于模拟的接口(interface),因此它不是一个选项。
您可以直接模拟 format 的 3-arg 重载:然后它应该允许您根据需要调用 format 的一个参数版本:
@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 将允许直接模拟最终格式方法,如果您愿意走那条路的话。
关于java - Mockito NumberFormat 在 when() 方法中模拟 NullPointer,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10598898/