Natrafiliśmy na naprawdę nieprzyjemny problem z Mockito.Mockito: co się stanie, jeśli zmieniony zostanie argument przekazywany na próbę?
Kod:
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));
}
}
powoduje Ten komunikat o błędzie jak:
Arguments are different! Wanted:
foo.bar([1,2,3]);
Actual invocation has different arguments:
foo.bar([]);
co się stało:
Mockito rekordy referencyjnych do list
zamiast kopii list
, więc w powyższym kodzie Mockito weryfikuje zamiast zmodyfikowaną wersję (pusta lista, []
) zamiast tego, który faktycznie przeszedł podczas wywoływania ([1,2,3]
)!
Pytanie:
Czy istnieje elegancki i czyste rozwiązanie tego problemu inne niż robi kopię obronną jak poniżej (które rzeczywiście pomaga, ale nie lubię tego rozwiązania)?
public void fun(){
list = Arrays.asList(1,2,3);
foo.bar(new ArrayList(list));
list.clear();
}
Nie chcemy zmodyfikować prawidłowy kod produkcyjną i zmniejszyć jego wydajność tylko rozwiązać problem techniczny z testu.
Zadaję to pytanie tutaj, ponieważ wydaje się, że jest to prawdopodobnie typowy problem z Mockito. Lub po prostu robimy coś nie tak?
PS. To nie jest prawdziwy kod, więc nie pytaj, dlaczego tworzymy listę, a następnie usuwamy ją itp. W prawdziwym kodzie mamy prawdziwą potrzebę zrobienia czegoś podobnego :-).
Czy rzeczywiście weryfikujesz na _różnej instancji_ tej samej klasy argumentów? – fge
@ fge Tak, nie mam dostępu do oryginalnej instancji w kodzie testowym, więc muszę utworzyć nową instancję argumentu w teście z oczekiwaną zawartością. –
Następnie zobacz moją odpowiedź – fge