Ответ 1
Используйте Answer
, чтобы проверить значение аргумента при вызове метода. Вы можете либо выбросить AssertionError
в пределах Answer
, если значение неверно, либо вы можете сохранить это значение, и выполнить свое утверждение в конце.
У меня есть класс Foo
, который является классом SUT и Bar
, который является его соавтором. Foo
вызывает run(List<Object> values)
в Bar
с "expectedList
" в качестве аргумента. Затем Foo
добавит еще несколько элементов к этому List
, чтобы его состояние отличалось от того, что было во время вызова run()
. Вот мой тестовый пример.
@Test
public void testFoo() {
Bar collaborator = spy(new Bar());
Foo sut = new Foo(collaborator);
verify(collaborator).run(expectedList);
}
Обратите внимание, что соавтор - это скорее объект-шпион, а не макет. Этот тестовый пример завершится неудачно, потому что даже если run()
был вызван с аргументом, равным expectedList
, он был изменен с тех пор, и его текущее значение больше не равно expectedList
. Тем не менее, это то, как он должен работать, поэтому мне интересно, есть ли способ, чтобы Mockito сохранял моментальный снимок параметров при вызове метода и проверял их на основе этих значений, а не самых последних значений.
Используйте Answer
, чтобы проверить значение аргумента при вызове метода. Вы можете либо выбросить AssertionError
в пределах Answer
, если значение неверно, либо вы можете сохранить это значение, и выполнить свое утверждение в конце.
Ответ Даудама ибн Карея работал у меня, но мне не хватало примера, также я использую Kotlin и Mockito-Kotlin, поэтому мое решение выглядит так:
class Foo(var mutable: String)
interface Bar {
fun run(foo: Foo)
}
@Test fun `validate mutable parameter at invocation`() {
val bar = mock<Bar>()
var valueAtInvocation: String? = null
whenever(bar.run(any())).then {
val foo = it.arguments.first() as Foo
valueAtInvocation = foo.mutable // Store mutable value as it was at the invocation
Unit // The answer
}
val foo = Foo(mutable = "first")
bar.run(foo)
valueAtInvocation isEqualTo "first"
foo.mutable = "second"
bar.run(foo)
valueAtInvocation isEqualTo "second"
}
valueAtInvocation
будет представлять значение изменяемого свойства foo.mutable
при последнем вызове bar.run(foo)
. Также возможно делать утверждения в блоке then {}
.
Вы не можете вызвать verify()
для объекта, который не является mock
. Это то, что вы имели в виду?
Bar collaborator = mock(Bar.class);
Foo sut = spy(new Foo(collaborator));
verify(collaborator).run(expectedList);
Почему бы вам не попробовать использовать захват аргументов, чтобы получить значение ожидаемого списка, когда оно было запущено, и затем вы можете сравнить его.
ArgumentCaptor<List> listCaptor = ArgumentCaptor.forClass(List.class);
verify(collaborator).run(listCaptor.capture());
assertEquals(expectedList, argument.getValue());