【问题标题】:Mockito.any returns nullMockito.any 返回 null
【发布时间】:2018-04-18 18:10:42
【问题描述】:

我正在尝试使用如下参数模拟静态方法:

Mockito.when(StaticClass.staticMethod(Mockito.any(A.class), 
                                      Mockito.any(B.class), SomeEnum.FOO))
       .thenReturn(true);

我添加了以下注释:

@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(Parameterized.class)
@PrepareForTest({StaticClass.class, A.class, B.class})

但 Mockito.any 总是返回 null。为什么?

【问题讨论】:

  • 正如我在回答中所写 - 您应该退后一步阅读minimal reproducible example 并相应地增强您的问题。
  • 我注意到您的问题仍然是“开放的”:您没有接受答案。请查看并决定是否要accept 回答。或者让我知道我是否可以做些什么来增强我的输入以使其被接受。接受有助于未来的读者确定问题是否得到解决,并对花时间回答你的人表示感谢。

标签: java unit-testing testing mockito powermock


【解决方案1】:

简答:使用doReturn().when() 而不是when().then()

长答案可以在这里找到: How do Mockito matchers work?

匹配器返回虚拟值,例如零、空集合或 null。 Mockito 尝试返回一个安全、适当的虚拟值,例如 0 表示 anyInt() 或 any(Integer.class) 或空列表 anyListOf(String.class)。但是,由于类型擦除,Mockito 缺少类型信息来返回任何值,但 any() 为 null

NullPointerException 或其他异常:调用 when(foo.bar(any())).thenReturn(baz) 实际上会调用 foo.bar(null), 您可能在收到 空参数。切换到 doReturn(baz).when(foo).bar(any()) 跳过 存根的行为。

旁注:这个问题也可以描述为,如何在对空参数进行前置条件检查的方法上使用 Mockito 匹配器?

【讨论】:

  • 您的Side Note 正是我在谷歌上搜索答案的确切问题。谢谢!
【解决方案2】:

首先,您不能将匹配器与实际参数混合使用。您也应该为 SomeEnum 参数使用匹配器:

Mockito.when(StaticClass.staticMethod(Mockito.any(A.class), 
                                      Mockito.any(B.class), Mockito.eq(SomeEnum.FOO))
       .thenReturn(true);

其次,any() 方法应返回 null。这正是他们所做的。如果您查看这些方法的代码,它们返回类类型的默认值,如果它是原始包装对象(如 Integer、Boolean 等),否则返回 null:

public <T> T returnFor(Class<T> clazz) {
    return Primitives.isPrimitiveOrWrapper(clazz) ? Primitives.defaultValueForPrimitiveOrWrapper(clazz) : null;
}

【讨论】:

  • 仍然返回 null :( 即使 Mockito.eq 返回 null 我在 @Before 方法中添加了 PowerMockito.spy(StaticClass.class);
  • 我刚刚意识到对于这些情况,any() 方法确实返回 null。它返回类的默认值,因此所有对象都为 null,而原始包装类(如 Integer)则返回默认原始值。所以这些方法返回null并没有错。您的测试实际上出了什么问题?
  • 我的staticMethod检查参数是否为空
【解决方案3】:

你搞错了。 any() 等匹配器方法的唯一目的是匹配在执行时传入的参数。

您使用这些方法来指示模拟框架您期望发生的调用。或者反过来,你用它们来表示:如果这个或那个作为论点出现,那么就做这个或那个。

因此,您绝对不关心匹配器调用的结果。

从这个意义上说,您的问题表明您对模拟框架的使用是错误的。因此,关于您当前的输入,我们可以给出的唯一答案是:A)做更多的研究如何使用模拟和 B)然后重新处理您的问题以明确您的问题。

【讨论】:

  • 如果您使用 Mockito 包装现有对象,调用 when(real.method(any(klass))) 最终会使用 null 调用真实方法,在测试设置期间抛出 NPE。假设更改对象real 超出了我的范围,还能做什么?
【解决方案4】:

因为是参数化测试,我在@Before方法中做了mockStatic。当我以相同的方法执行 mockStatic 时,它可以工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-21
    • 2020-06-19
    • 2011-10-15
    相关资源
    最近更新 更多