Mockito可以根据方法调用时的值验证参数吗?

时间:2012-01-31 19:36:02

标签: java unit-testing 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在调用方法时存储参数的快照,并根据这些值而不是最近的值来验证它们。

4 个答案:

答案 0 :(得分:12)

在调用方法时,使用Answer检查参数的值。如果值错误,您可以在AssertionError内抛出Answer,或者您可以存储该值,并在结尾处执行您的断言。

答案 1 :(得分:1)

The answer of Dawood ibn Kareem为我工作,但我缺少一个例子,我也使用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 {}块内进行断言。

答案 2 :(得分:0)

您无法在非verify()的对象上调用mock。这是你的意思吗?

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

答案 3 :(得分:-2)

为什么不尝试使用参数捕获来获取期望列表的值,然后你可以比较它。

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

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

assertEquals(expectedList, argument.getValue());