是否可以在没有Mockito.verify的情况下测试方法调用?

时间:2019-07-31 04:43:51

标签: unit-testing junit mockito

如果我需要测试受测试的中的方法是否被调用,可以在没有Mockito(或任何与此相关的模拟工具)的情况下完成吗?

原因是,无论我在哪里阅读有关Mockito和类似工具的信息,都说永远不应该模拟CUT,而应该模拟其依赖关系(这一部分很清楚)。

因此,如果是这样,那么只剩下2个选择:

  1. 还有其他无需模拟的测试方式

  1. 调用该方法的事实本身不应进行测试,而应具有某些副作用或方法返回值

例如(平凡的和非现实的),类MyClass可以有2种方法:A()B()。条件根据某个内部状态调用B。 安排状态并通过调用A()进行操作后,我们要断言已调用B()。 要么不模拟整个CUT,要么不可能在单个类中像这样的2种方法始终是违反SRP的气味,并要求重新设计B()实际上应该(模拟)对MyClass CUT的依赖。

那么,什么是正确的?

2 个答案:

答案 0 :(得分:1)

看看Mockito文档(https://static.javadoc.io/org.mockito/mockito-core/3.0.0/org/mockito/Mockito.html#13

使用Spy时,您可以将“方法”“替换”在要测试的同一类中。

@ExtendWith(MockitoExtension.class)
public class Test {

    class MyClass {

        public void a() {
            b();
        }

        public void b() {

        }
    }

    @Test
    public void test() {

        MyClass testClass = new MyClass();
        MyClass spy = Mockito.spy(testClass);

        Mockito.doNothing().when(spy).b();

        spy.a();

        Mockito.verify(spy, Mockito.times(1)).b();
    }   
}

所以这是否应该做是一个不同的问题;)
我认为这很大程度上取决于B()实际在执行什么方法,以及首先是否应该将其作为MyClass的一部分。


  

如果不模拟整个CUT,这是不可能的

在这种情况下,我们不会仅模拟您不想调用的方法来模拟整个CUT。


  

原因是,无论我在哪里阅读有关Mockito和类似工具的信息,都说永远不应该模拟CUT,而应该模拟其依赖关系(这一部分很清楚)。

我认为,这种说法与间谍活动并不完全准确。
在我眼中,监视的全部目的是在测试的班级上使用它。为什么一个人想窥探一开始就不应该参与的依赖呢?

答案 1 :(得分:1)

通常,我什至不使用间谍程序,相反,我更喜欢以对所写的任何类编写代码的方式来编写代码:

  • 我只测试非私有方法,因为它们是被测类的入口点。因此,在您的示例中,如果a()调用b(),则b()可能是私有的,因此不应进行测试。概括地说,a()是类“可以做的”(一种行为),因此我测试了行为,而不是方法本身。如果这种行为在内部调用了其他东西-那么,这是该类的内部问题,如果可能的话,我不会对该类的内部工作方式做任何假设,并且始终喜欢“白盒”测试。 我只在测试中测试“一种”非私有方法。

  • 所有方法都应返回某些内容(最佳选择)或至少调用依赖项,或更改被测对象的内部状态。依赖项列表总是很容易理解,我无法在不提供依赖项列表的情况下实例化CUT对象。例如,使用构造函数依赖项注入是实现此目的的一种好方法。实际上,我仅嘲笑依赖项,而从不嘲笑/监视CUT。依赖性永远不会是静态的,而是会注入的。

现在有了这些简单的规则,基本上需要“ 测试被测类中的方法是否已被调用”基本上可以归结为以下其中之一:

  • 您正在谈论私有方法。在这种情况下-请勿测试,仅测试公共事物。

  • 该方法是公共的-在这种情况下,您需要在单元测试中显式调用它,因此它是不相关的。

现在让我们问为什么,如果要调用CUT中的方法,是否要测试

如果要确保它更改了某些内容。如果此“某物”在类中-换句话说,其内部状态已更改,请通过调用允许查询状态的另一种方法来检查测试是否确实在该状态中完成更改 如果此“某物”是由依赖项管理的代码,请创建此依赖项的模拟并验证是否使用期望的参数调用了它。

相关问题