6

我想为一个方法使用两个自定义匹配器。基本上,如果我通过方法 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(),但我的匹配器完全按照它们应该的方式工作。

那么有什么关系呢?为什么会这样?我的变通办法是弥补这种古怪行为的充分方法,还是我做错了?

4

1 回答 1

11

IsNonEmpty.matches()在存根的第二行调用的原因是Mockito.argThat(new IsEmpty())返回 null,然后将其传递给mockHTable.get(). 这个调用必须与之前的存根进行检查,看它是否匹配;这意味着调用IsNonEmpty.matches().

我不知道为什么这会让你的测试失败——如果没有看到所有的代码就很难说清楚。

但是,我强烈建议您使用,doReturn...when而不是when...thenReturn在您必须多次存根同一模拟时使用。如果你这样做,你就不会遇到这样的问题。事实上,尽管大多数人更doReturn...when喜欢.when...thenReturndoThrowdoAnswerwhen...thenReturn

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

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 问题的原因出乎意料。

于 2012-04-27T06:06:16.343 回答