Мы столкнулись с действительно неприятной проблемой с Мокито.Mockito: что, если аргумент, переданный макету, изменен?
Код:
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));
}
}
Это вызывает сообщение об ошибке, как:
Arguments are different! Wanted:
foo.bar([1,2,3]);
Actual invocation has different arguments:
foo.bar([]);
Что только что произошло:
Mockito записи эталонные к list
, а не копию list
, поэтому в коде выше Mockito проверяет измененную версию (пустой список, []
) вместо того, который фактически прошел во время вызова ([1,2,3]
)!
Вопрос:
Есть ли элегантное и чистое решение этой проблемы, кроме делает защитную копию, как показано ниже (который на самом деле помогает, но нам не нравится это решение)?
public void fun(){
list = Arrays.asList(1,2,3);
foo.bar(new ArrayList(list));
list.clear();
}
Мы не хотим, чтобы изменить правильный код производства и снижают его производительность только для устранения технических проблем с тестом.
Я задаю этот вопрос здесь, потому что это, возможно, общая проблема с Mockito. Или мы просто делаем что-то не так?
PS. Это не настоящий код, поэтому, пожалуйста, не спрашивайте, почему мы создаем список, а затем очищаем его и т. Д. В реальном коде нам действительно нужно сделать что-то подобное :-).
Действительно ли вы проверяете экземпляр _different экземпляра того же класса аргументов? – fge
@fge Да, у меня нет доступа к исходному экземпляру в тестовом коде, поэтому мне нужно создать новый экземпляр аргумента в тесте с ожидаемым контентом. –
Тогда см. Мой ответ – fge