Wir stießen auf wirklich unangenehme Probleme mit Mockito.Mockito: Was passiert, wenn das Argument zum Mock verändert wird?
Code:
public class Baz{
private Foo foo;
private List list;
public Baz(Foo foo){
this.foo = foo;
}
public void invokeBar(){
list = Arrays.asList(1,2,3);
foo.bar(list);
list.clear();
}
}
public class BazTest{
@Test
void testBarIsInvoked(){
Foo mockFoo = mock(Foo.class);
Baz baz = new Baz(mockFoo);
baz.invokeBar();
verify(mockFoo).bar(Arrays.asList(1,2,3));
}
}
Dies verursacht Fehlermeldung wie:
Arguments are different! Wanted:
foo.bar([1,2,3]);
Actual invocation has different arguments:
foo.bar([]);
Was gerade passiert ist:
Mockito Aufzeichnungen Referenz-list
eher als Kopie list
, also im obigen Code verifiziert Mockito gegen geänderte Version (leere Liste, []
) statt zu der, die tatsächlich während des Aufrufs übergeben wurde ([1,2,3]
)!
Frage:
Gibt es eine elegante und saubere Lösung für dieses Problem anders als wie unten eine defensive Kopie zu tun (was tatsächlich hilft, aber wir haben nicht diese Lösung mögen)?
public void fun(){
list = Arrays.asList(1,2,3);
foo.bar(new ArrayList(list));
list.clear();
}
Wir wollen nicht richtigen Produktionscode zu modifizieren und seine Leistung reduzieren nur technisches Problem mit Test zu beheben.
Ich stelle diese Frage hier, weil es ein mögliches allgemeines Problem mit Mockito zu sein scheint. Oder wir machen nur etwas falsch?
PS. Das ist kein richtiger Code, also frag bitte nicht, warum wir eine Liste erstellen und dann löschen usw. In echtem Code haben wir ein echtes Bedürfnis, etwas ähnliches zu tun :-).
Verifizieren Sie tatsächlich eine _different-Instanz_ derselben Argumentklasse? – fge
@fge Ja, ich habe keinen Zugriff auf die ursprüngliche Instanz im Testcode, daher muss ich eine neue Instanz des Arguments im Test mit dem erwarteten Inhalt erstellen. –
Dann sehe meine Antwort – fge