Home > Software engineering >  How to verify a method inside a method is called in mockito
How to verify a method inside a method is called in mockito

Time:08-05

I was doing some unit testing in flutter with mockito, and I feels unable to verify a method is called within another method. The code I've written so far as follows,

The class I want to test

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

  void callMe() {}
}

Mocked class

class MockA extends Mock implements A {}

The test I wrote,

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

When I run the above test I am getting an error

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

If i verify doSomething is called it works, but for a call on callMe within doSomething doesn't work. Is this the default behavior or am I doing something wrong? Please note I need to verify the callMe() method is called when doSomething() is called.

CodePudding user response:

You mocked A and replaced it with MockA. Mocks have no implementation. MockA.doSomething() does nothing and does not and cannot call MockA.callMe().

That A.doSomething() calls A.callMe() should be considered an implementation detail of of doSomething(); making a test rely on that would tightly couple the test to the specific implementation and would be brittle.

You can't use a mock to verify the implementation of the thing being mocked. If you want to verify the implementation of A.doSomething(), you instead should use an actual object and verify observable properties on that object.

But if you still really want to do this, then you would need to modify A to not call methods on itself and to instead call methods on a provided object (i.e., "dependency injection"). For example:

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

It's a bit unusual for a class to depend on a mock of itself, however, and it would not scale if you then want to verify calls made by callMe().

Another approach that would scale better (but with significantly more work) would be to create your own fake class that tracks method calls:

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

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

  @override
  void callMe() {
    callMeCallCount  = 1;
    super.callMe();
  }
}

But again, that's very brittle, and I would not recommend it.

  • Related