Reputation: 1861
A test doesn't pass, this failure occurs:
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"]}}
);
You can see what my problem is immediately from the output of the failure. There is no difference. The toString
method might be deceiving, maybe equals
method returns false
for the DBObject
s... as I state below, I am not sure how to check this, but checking equality of two "queryBuilt" same DBObject
s returned true
.
The test is short and looks like this:
@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);
}
with the getLemma method like this:
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");
}
The code doesn't even get lower than to if(cursor == null)
part, since the stub is not working. I created two distinct DBObject
s by running the QueryBuilder
twice and then checked if they are equal (I don't know how the implementation of equals
Mongo DBObject
lookslike - edit: compares map entries).
I have no clue, why the failure occurs.
I have tried Biju Kunjummen's answer and it did not help at first, but I tried this:
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));
and the assert fails. So I can see the problem is not with Mockito, but the DBObjects do not match, even though they should. To me, semantically the queries are equal. (answered below): it seems like, if a Map.entry
has an Object[]
as a value which has the same contents as the compared Object[]
equals
goes false
, if the Object[]
is not the same reference as the compared one.
Upvotes: 0
Views: 1417
Reputation: 1861
So: verify
method was checking, if I was using the same queryObj
as attribute. Since it used equals
and since DBObject
is compared by the mapped values via Map
equals
method, it checked the equality of Map
entry
s. And I believe, that it did not compare the two Object[]
arrays for it's contents, but checked the references and found them not matching. Thus equality was false
and verify
said that it was expecting different parameter.
I replaced the use of Object[]
with List<>
and now the verify
method is happy - it passes.
The test was still not working, but it was for completely different reasons, which I (might) describe in a different question: //will post here, if I find looking for an answer important enough.
Anyways, the test now works ok like this:
@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);
}
and the implementation of 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");
}
I could not use
criteria.add(word);
//....
criteria.remove(0);
for unknown reasons, which I (might) ask in the next question. (I will post the link here, if I create the question)
Upvotes: 1
Reputation: 49935
Possibly because your DBObject.equals
(and hashcode) is not correctly implemented, a quick way to check it would be to try this:
DBObject queryObj1 = QueryBuilder.start("declensions").in(criteria).get();
DBObject queryObj2 = QueryBuilder.start("declensions").in(criteria).get();
assertTrue(queryObj1.equals(queryObj2))
This would likely fail, and this is the reason for the Mock assertion error.
Upvotes: 1