当 return 值为枚举类型时,函数执行 return null

Function does return null when return value is of enum type

我正在为 TestClass 中的函数编写单元测试,它检查 org.apache.hadoop.hbase.Cell 的内容和 return 的枚举类型。枚举如下:

public enum Enum_1 {
  SKIP,
  EXIT_1,
  EXIT_2
}

函数如下:

public ENUM_1 check (Cell cell, String str, int someInt) {
  String cellValue = new String(cell.getValueArray(), StandardCharsets.UTF_8);
  if(//case 1, doesn't fall here) {
      /.../
      return SKIP;
  }
  else if(//case 2, doesn't fall here neither){
      /.../
      return EXIT_1;
  }
  //100% sure falls in this case
  else {
      Long long1 = getLong(str, someInt);
      Long long2 = Long.parseLong(cellValue);
      if(long1 > long2) {
        return EXIT_2;
      }
  }
  return SKIP;
}

在单元测试中,我使用 mockito 使函数 getLong(str, someInt) return 具有一定的值。单元测试代码如下所示:

@Test
public void test1() {
    TestClass testClass = mock(TestClass.class);
    Cell mockCell = mock(Cell.class);
    String str = "str";
    int someInt = 1;
    when(mockCell.getValueArray()).thenReturn("500".getBytes());
    when(testClass.getLong(same(str), same(someInt)).thenReturn(Long.valueOf(400));

    TestClass.ENUM_1 result = testClass.check(mockCell, str, someInt);
    assertEquals(result, TestClass.ENUM_1.SKIP);
}

但是当我 运行 测试时,由于 resultnull,所以它失败了。

同样,我 100% 确定 else{} 函数 check() 中传递的值。

问题是:为什么我从具有 return ENUM 类型值的函数中得到 null?我对 Mockito 做错了什么吗?感谢任何帮助。

why am i getting null from a function with return value of ENUM type?

您将得到 null,因为调用的方法 returned null。在这方面,枚举不是特殊类型;枚举引用可以为空,就像任何其他对象引用一样。

Is this something i did wrong with Mockito?

是的。

看起来你模拟了你正在测试的class,这几乎肯定不是你想要做的(因为那样你就没有测试真正的代码 class)。然后,您为 getLong() 方法定义了一个存根 return,但没有告诉 mock 关于 check() 方法的任何信息。

因此,当您调用 testClass.check(mockCell, str, someInt) 时,模拟采用默认行为,即 return null。

要修复,请不要嘲笑它 TestClass!相反,构建它的一个实例,因此您的 check() 调用将调用第二个代码块中显示的实际方法。

为答案竖起大拇指!! @Andrzej
放眼大局。
一般来说,联合测试执行测试一小段代码,通常是一个方法。 所以预计要测试的方法不会被模拟。所以有 stubing 的概念,即您认为不应该成为此单元测试的一部分的存根代码段。

因此,根据 getLong() 原则,对这个方法的依赖代表了类似的责任,或者它必须参与这个功能。如果是这样,那么它应该是 private
如果 getLong() 不应该承担这个 class 的责任,那么它应该是另一个 class 的一部分,因此 单一责任原则 开始。

无论这些最佳实践如何,您仍然可以这样做, 你只需要调用 thenCallRealMethod() 并从同一个 class 调用 getLong() 你必须在 TestClassSpy 它会工作正常。

但我们应该记住 Mockito 不允许模拟私有和静态方法是有原因的。 快乐编码!!!