如何验证构造函数中的方法调用?

Jay*_*Jay 1 java junit unit-testing mockito powermock

我有一个构造函数,它调用两个方法。它们都是无效的,我只是想验证它们是否被调用。

文件

public class Foo {

    public Foo(String name, Object obj) {
         init(name);
         doSomething(obj);
    }
}
Run Code Online (Sandbox Code Playgroud)

测试文件

@Test
public void constructor_test throws Exception {
    Foo foo = Mockito.mock(Foo.class);
    PowerMockito.whenNew(Foo.class).withAnyArguments().thenReturn(foo);
    Foo f = new Foo("name");
    verify(f).init(Mockito.anyString()); 
    verify(f).doSomething(Mockito.any(Object.class)); 
}
Run Code Online (Sandbox Code Playgroud)

单元测试失败并显示一条消息,指出与模拟foo.init() 的交互为零.

如何验证构造函数中的方法调用?

Sam*_*der 5

你不能通过检查你的状态来测试Foo吗?

即是否有一些外部可见的getName()函数可以调用并验证名称是否已在构造函数中正确设置?这比检查私有方法的调用更可取,因为只要行为和外部状态相同,您就可以重构类的内部工作而无需更改测试。

如果您发现自己想要检查是否在单元测试中调用了私有方法,那么这是一种气味,我认为应该重新考虑您的方法。一些其他的问题已经涵盖了类似的区域。

如果这些方法与某些外部组件交互,那么您可以像通常使用任何方法一样模拟这些组件,然后验证交互是否符合您的预期。这种交互是发生在一种方法还是另一种内部应该是类的实现细节,而在Foo外部你不应该关心。

感觉就像你想要的方法会导致一个非常脆弱的测试,随着Foo更改的实施需要经常更改。

至于您的实际问题,我不确定您是否可以做您想做的事,因为根据我的理解,您Foo不是“真实”Foo而是模拟,Foo因此不会调用真正的构造函数。

如果您能够做到,则可以通过创建“PartialMock”并将其委托给基础类来实现。我对 Mockito 只有一点经验,但我认为这种方法在我熟悉的其他一些 (.NET) 模拟框架中可能是可能的,虽然我还没有尝试过,但它可能会给你一些额外的话提升你的谷歌 foo 。

  • @Jay 太棒了。恕我直言,如果您的测试对被测事物的实现方式不可知,而是依靠行为/状态来验证他们的期望,那么您的测试总是会更好。Mock 应该是测试的最后手段,而不是第一个调用端口,并且每个 Mock 都会引入耦合,这意味着当您想要更改类行为时,您也必须在测试中更改它。 (2认同)