繁体   English   中英

Mockito NumberFormat在when()方法中模拟NullPointer

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM