如何在mockito中验证方法内部的方法被调用

SVG*_*SVG 4 mockito dart flutter

我正在使用mockito在flutter中进行一些单元测试,我感觉无法验证一个方法是否在另一个方法中被调用。到目前为止我写的代码如下:

我想测试的班级

class A {
  void doSomething() {
    callMe();
  }

  void callMe() {}
}
Run Code Online (Sandbox Code Playgroud)

模拟类

class MockA extends Mock implements A {}
Run Code Online (Sandbox Code Playgroud)

我写的测试,

test("Test method is called", () {
    A a = new MockA();
    a.doSomething();
    verify(a.callMe()).called(1);
  });
Run Code Online (Sandbox Code Playgroud)

当我运行上述测试时出现错误

No matching calls. All calls: MockA.doSomething()
(If you called `verify(...).called(0);`, please instead use `verifyNever(...);`.)
Run Code Online (Sandbox Code Playgroud)

如果我验证 doSomething 被调用,它可以工作,但是对于 doSomething 中的 callMe 调用则不起作用。这是默认行为还是我做错了什么?请注意,我需要验证调用 doSomething() 时是否调用了 callMe() 方法。

jam*_*lin 7

您嘲笑A并将其替换为MockA. 模拟没有实现。MockA.doSomething() 什么都不做,不调用,也不能调用MockA.callMe()

A.doSomething()调用A.callMe()应被视为 的实现细节doSomething();进行测试依赖于此会将测试与特定实现紧密耦合并且会很脆弱。

您不能使用模拟来验证被模拟事物的实现。如果您想验证 的实现A.doSomething(),则应该使用 的实际(未模拟)实例A,然后验证该实例上的可观察属性。

但如果您仍然确实想这样做,那么您需要修改A为不调用自身的方法,而是调用提供的对象上的方法(即“依赖注入”)。例如:

class A {
  final late A a;

  A({A? a}) {
    this.a = a ?? this;
  }

  void doSomething() {
    a.callMe();
  }

  void callMe() {}
}

test("Test method is called", () {
    var mockA = MockA();
    var actualA = A(a: mockA);
    actualA.doSomething();
    verify(mockA.callMe()).called(1);
  });
Run Code Online (Sandbox Code Playgroud)

然而,类依赖于自身的模拟有点不寻常,如果您随后想要验证callMe().

另一种可以更好地扩展(但需要更多工作)的方法是创建自己的假类来跟踪方法调用:

class TrackedA implements A {
  int doSomethingCallCount = 0;
  int callMeCallCount = 0;

  @override
  void doSomething() {
    doSomethingCallCount += 1;
    super.doSomething();
  }

  @override
  void callMe() {
    callMeCallCount += 1;
    super.callMe();
  }
}
Run Code Online (Sandbox Code Playgroud)

但同样,这非常脆弱,我不会推荐它。