java - 当我将多个自定义匹配器分配给一个方法时,Mockito 的行为很奇怪

标签 java mocking mockito matcher hamcrest

我想为一个方法使用两个自定义匹配器。基本上,如果我传递方法 VALUE_A,我希望它返回 RESULT_A,如果我传递它 VALUE_B,我希望它返回 RESULT_B。所以这是一段代码摘录:

class IsNonEmpty extends ArgumentMatcher<Get> {
    public boolean matches(Object get) {
        //For some reason, this method is called when I assign the IsEmpty matcher to MockHtable.get()
        //When this happens, the value of the get argument is null, so this method throws an NPE

        return Arrays.equals(((Get) get).getRow(), SERIALIZATION_HELPER.getValidBytes(key)); 
    }
}

class IsEmpty extends ArgumentMatcher<Get> {
    public boolean matches(Object get) {
        return !(Arrays.equals(((Get) get).getRow(), SERIALIZATION_HELPER.getValidBytes(key))); 
    }
}      

[...]

//This line executes just fine
Mockito.when(mockHTable.get(Mockito.argThat(new IsNonEmpty()))).thenReturn(dbResult);

[...]

//This line calls IsNonEmpty.matches() for some reason.  IsNonEmpty.matches() throws an NPE
Mockito.when(mockHTable.get(Mockito.argThat(new IsEmpty()))).thenReturn(emptyResult);

当我将 IsEmpty 自定义匹配器分配给 mockHTable.get() 方法时,它会调用 IsNonEmpty.matches() 函数。不知道为什么要这样做。所以我将 IsNonEmpty 类更改为:

class IsNonEmpty extends ArgumentMatcher<Get> {
    public boolean matches(Object get) {
        //For some reason, this method is called when I assign the IsEmpty matcher.  Weird, no?
        if(get == null) {
            return false;
        }

        return Arrays.equals(((Get) get).getRow(), SERIALIZATION_HELPER.getValidBytes(key)); 
    }
}

然后一切正常!当我将 IsEmpty 匹配器分配给 mockHTable.get() 函数时,仍然会调用 IsNonEmpty.matches(),但我的匹配器完全按照它们应有的方式工作。

那到底是怎么回事呢?为什么会这样?我的变通办法是否足以弥补这种古怪行为,还是我做错了?

最佳答案

在 stub 的第二行调用 IsNonEmpty.matches() 的原因是 Mockito.argThat(new IsEmpty()) 返回 null,即然后传递给 mockHTable.get()。必须根据之前的 stub 检查此调用,以查看它是否匹配;这意味着调用 IsNonEmpty.matches()

我不确定为什么这会使您的测试失败 - 如果不查看所有代码就很难判断。

但是,我强烈建议您在必须多次对同一个模拟进行 stub 时使用 doReturn...when 而不是 when...thenReturn 。如果你这样做,你就不会遇到这样的问题。事实上,我更喜欢使用 doReturn...when 而不是 when...thenReturn 总是(同样地 doThrow doAnswer),尽管大多数人更喜欢 when...thenReturn

使用 doReturn...when 语法重写您的 stub 行之一,如下所示。另一个类似。

Mockito.doReturn(dbResult).when(mockHTable).get(Mockito.argThat(new IsNonEmpty()));  

最后,代表 Mockito 开发团队(我是其中一员)发出请求。如果您认为这里的 Mockito 中存在错误 - 从您的描述来看,我认为很可能存在 - 请要么

  • 向 Mockito 邮件组发送消息 (mockito@googlegroups.com) 或
  • 在 Mockito 问题列表 (http://code.google.com/p/mockito/issues/list) 上提出问题。

如果您实际上可以发布一个完整的示例,而不仅仅是您认为的关键行,这对 Mockito 团队很有用 - 有时 Mockito 问题的原因出在非常意想不到的地方。

关于java - 当我将多个自定义匹配器分配给一个方法时,Mockito 的行为很奇怪,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10342461/

相关文章:

python - 如何修补日期时间的 now 方法,同时保留其他方法?

java - 需要访问存储库的测试方法

java - 如何告诉 Mockito 模拟对象在下次调用时返回不同的东西?

java - 过程或函数 'search_words1' 需要参数 '@result' ,但未提供该参数

java - 在 Maven 中存储程序集文件的正确位置是什么?

database - Mock 框架可以为我做这个吗?

Python Mocking - 如何修补函数内的变量

mockito - 使用 Http.outboundGateway() 和配置的 RestTemplate 测试 spring 集成流程

java - 在实现检测输入是否为整数的系统时遇到困难

java - 使用 GSON 解析 key - 对象 JSON