【问题标题】:How do I verify a method call that is in a constructor?如何验证构造函数中的方法调用?
【发布时间】:2014-05-29 11:47:16
【问题描述】:

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

Foo.java

public class Foo {

    public Foo(String name, Object obj) {
         init(name);
         doSomething(obj);
    }
}

FooTest.java

@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)); 
}

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

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

【问题讨论】:

  • 在这种情况下你真的需要使用模拟吗?如果这些方法更改Foo 的状态,最好检查该状态。如果它们调用了一些外部组件,您可以改为模拟这些组件。

标签: java unit-testing junit mockito powermock


【解决方案1】:

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

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

如果您发现自己想要检查是否在单元测试中调用了私有方法,那么这是一种味道,我认为应该重新考虑您的方法。一些other questionsalready covered 类似的区域。

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

感觉你想要的方法会导致一个非常脆弱的测试,随着Foo 的实现发生变化,需要经常更改它。

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

如果可以的话,可以创建一个“PartialMock”并将其委托给底层类。我对 Mockito 只有一点经验,但我认为这种方法在我熟悉的其他一些(.NET)模拟框架中可能是可行的,虽然我没有尝试过,但它可能会给你一些额外的词来提升您的 google foo 与。

【讨论】:

  • 谢谢。为什么不创建模拟对象的原因是有道理的。通过断言对象的状态符合我的预期,我通过了单元测试。
  • @Jay 太好了。恕我直言,如果他们不知道被测事物的实现方式,而是依靠行为/状态来验证他们的期望,那么您的测试总是会更好。模拟应该是测试的最后手段,而不是第一个调用端口,每个模拟都会引入耦合,这意味着当您想要更改类行为时,您也必须在测试中更改它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-17
  • 2015-10-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-18
相关资源
最近更新 更多