Подтвердить что ты не робот

Может ли Mockito проверять параметры на основе их значений во время вызова метода?

У меня есть класс 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 сохранял моментальный снимок параметров при вызове метода и проверял их на основе этих значений, а не самых последних значений.

4b9b3361

Ответ 1

Используйте Answer, чтобы проверить значение аргумента при вызове метода. Вы можете либо выбросить AssertionError в пределах Answer, если значение неверно, либо вы можете сохранить это значение, и выполнить свое утверждение в конце.

Ответ 2

Ответ Даудама ибн Карея работал у меня, но мне не хватало примера, также я использую 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 {}.

Ответ 3

Вы не можете вызвать verify() для объекта, который не является mock. Это то, что вы имели в виду?

Bar collaborator = mock(Bar.class); 
Foo sut = spy(new Foo(collaborator));
verify(collaborator).run(expectedList);

Ответ 4

Почему бы вам не попробовать использовать захват аргументов, чтобы получить значение ожидаемого списка, когда оно было запущено, и затем вы можете сравнить его.

ArgumentCaptor<List> listCaptor = ArgumentCaptor.forClass(List.class);

verify(collaborator).run(listCaptor.capture());

assertEquals(expectedList, argument.getValue());