Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can Mockito verify parameters based on their values at the time of method call?

I have a Foo class which is SUT and a Bar class, which is its collaborator. Foo calls run(List<Object> values) on the Bar with "expectedList" as an argument. Then, Foo will add a few more elements to this List so that its state will be different from what it was at the time of calling run(). Here's my test case.

@Test
public void testFoo() {
    Bar collaborator = spy(new Bar()); 
    Foo sut = new Foo(collaborator);
    verify(collaborator).run(expectedList);
}

Note that the collaborator is actually a spy object rather than a mock. This test case will fail because even though run() was called with an argument equal to expectedList, it was modified since and its current value no longer equals expectedList. However, this is the way it is supposed to work, so I'm wondering if there's a way to have Mockito store the snapshot of parameters when a method is called and verify them based on these values rather than the most recent values.

like image 840
Tom Tucker Avatar asked Jan 31 '12 19:01

Tom Tucker


People also ask

Does Mockito verify call the method?

Mockito. verify() will just verify that an invocation was done on a mock during the method execution. It means that if the real implementation of the mocked class doesn't work as it should, the test is helpless.

How does verify work in Mockito?

Mockito verify() method can be used to test number of method invocations too. We can test exact number of times, at least once, at least, at most number of invocation times for a mocked method. We can use verifyNoMoreInteractions() after all the verify() method calls to make sure everything is verified.

When to Use assert and verify in Mockito?

The Assert command is used to validate critical functionality. If this validation fails, then the execution of that test method is stopped and marked as failed. In the case of Verify command, the test method continues the execution even after the failure of an assertion statement.


2 Answers

Use an Answer to check the value of the argument when the method is called. You can either throw an AssertionError within the Answer if the value is wrong, or you can store the value, and do your assertion at the end.

like image 186
Dawood ibn Kareem Avatar answered Oct 03 '22 17:10

Dawood ibn Kareem


The answer of Dawood ibn Kareem worked for me but I lacked an example, also I use Kotlin and Mockito-Kotlin, so my solution is like this:

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 will represent the value of the mutable property foo.mutable at the last invocation of bar.run(foo). Should also be possible to do assertions within the then {} block.

like image 36
Love Avatar answered Oct 03 '22 16:10

Love