Mockito测试失败 - 参数(Mongo DBObjects)是不同的(不是!



编辑:这个问题在下面提出了一个更具体的问题。

测试未通过,则会发生以下故障:

Argument(s) are different! Wanted:
declColl.find(
{ "declensions" : { "$in" : [ "testtest"]}}
);
-> at cz.xxx.CzechMongoWordDeclensionsRetrieverTest.getLemmaTest(CzechMongoWordDeclensionsRetrieverTest.java:63)
Actual invocation has different arguments:
declColl.find(
{ "declensions" : { "$in" : [ "testtest"]}}
);

您可以从失败的输出中立即看到我的问题是什么。没有区别。toString方法可能是欺骗性的,也许equals方法返回falseDBObject...正如我在下面所说,我不确定如何检查这一点,但是检查两个"queryBuilt"相同DBObject的相等性返回true

测试很短,如下所示:

@InjectMocks
private CzechMongoWordDeclensionsRetriever declRetriever;
@Mock
private DBCollection declColl;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
Object[] criteria = new String[1];
criteria[0] = "testtest";
//mocks init
DBCursor cur = mock(DBCursor.class);
DBObject queryObj = QueryBuilder.start("declensions").in(criteria).get();
when(declColl.find(queryObj)).thenReturn(cur);
when(cur.size()).thenReturn(1);
when(cur.next()).thenReturn(new BasicDBObject("lemma", "testtest"));
}
@Test
public void getLemmaTest() {
Object[] criteria = new String[1];
criteria[0] = "testtest";
DBObject queryObj = QueryBuilder.start("declensions").in(criteria).get();
String toTest = "testtest";
String testResult = declRetriever.getLemma(toTest);
verify(declColl).find(queryObj);
}

使用像这样的 getLemma 方法:

public String getLemma(String word) {
criteria[0] = word;
DBObject lemmaObj = QueryBuilder.start("declensions").in(criteria).get();
DBCursor cursor = declColl.find(lemmaObj);
if(cursor == null)     return null;
if(cursor.size() > 1)  return null; 
if(cursor.size() == 0) return null; 
return (String) cursor.next().get("lemma");
}

代码甚至不低于if(cursor == null)部分,因为存根不起作用。我通过运行两次QueryBuilder创建了两个不同的DBObject,然后检查它们是否相等(我不知道equalsMongoDBObject的实现如何 - 编辑:比较地图条目)。

我不知道为什么会失败。

编辑:(这应该是一个新问题吗?

我试过Biju Kunjummen的答案,一开始没有帮助,但我试过这个:

Object[] criteria = new String[1];
criteria[0] = "testtest";
DBObject queryObj = QueryBuilder.start("declensions").in(criteria).get();
Object[] criteria2 = new String[1];
criteria2[0] = "testtest";
DBObject queryObj2 = QueryBuilder.start("declensions").in(criteria).get();
assertTrue(queryObj.equals(queryObj2));

并且断言失败。所以我可以看到问题不在于 Mockito,而是 DBObjects 不匹配,即使它们应该匹配。对我来说,查询在语义上是相等的。(在下面回答):似乎,如果一个Map.entry有一个Object[]作为值,该值与比较Object[]equalsfalse具有相同的内容,如果Object[]与比较的引用不同。

可能是因为您的DBObject.equals(和哈希码)未正确实现,检查它的快速方法是尝试以下操作:

DBObject queryObj1 = QueryBuilder.start("declensions").in(criteria).get();
DBObject queryObj2 = QueryBuilder.start("declensions").in(criteria).get();
assertTrue(queryObj1.equals(queryObj2))

这可能会失败,这就是模拟断言错误的原因。

所以:verify方法是检查我是否使用与属性相同的queryObj。由于它使用了equals并且由于DBObject通过Mapequals方法通过映射值进行比较,因此它检查了Mapentrys的相等性。而且我相信,它没有比较两个Object[]数组的内容,而是检查了引用并发现它们不匹配。因此,平等是false的,verify说它期待不同的参数。

我用List<>替换了Object[]的使用,现在verify方法很高兴 - 它通过了。

测试仍然不起作用,但它是出于完全不同的原因,我(可能)在不同的问题中描述://将在这里发布,如果我发现寻找答案足够重要。

无论如何,测试现在可以像这样工作:

@Test
public void getLemmaTest() {
//... now I use List<String> instead of Object[]. declColl is already stubbed 
// to return something, when a find(queryObj) is called.
List<String> criteriaColl = new ArrayList<>();
criteriaColl.add("testtest");
DBObject queryObj = QueryBuilder.start("declensions").in(criteriaColl).get();
String expResult = "testtest";
String toTest = "testtest";
String testResult = declRetriever.getLemma(toTest);
verify(declColl).find(queryObj);
assertEquals(expResult, testResult);  
}

以及getLemma的实现。

public String getLemma(String word) {
criteria.set(0, word);
DBObject lemmaObj = QueryBuilder.start("declensions").in(criteria).get();
DBCursor cursor = declColl.find(lemmaObj);
if(cursor == null)      return null;
if(cursor.size() > 1)   return null;
if(cursor.size() == 0)  return null;
return (String) cursor.next().get("lemma");
}

我无法使用

criteria.add(word);
//....
criteria.remove(0);

出于未知的原因,我(可能)在下一个问题中问。(如果我创建问题,我将在此处发布链接)

相关内容

  • 没有找到相关文章

最新更新