Python Mock call order with incomplete call list

Viewed 207

My goal is to find out whether a function from one object was called before another function of another object.

class A:
    def foo( self ):
       ...

    def foo2( self ):
       ...

class B:
    def goo( self ):
       ...

class C:
    def func( self, a: A, b: B ):
       a.foo()
       a.foo2()
       b.goo()

With my unit test, I would like to find out whether a.foo() was called before b.goo(). I already tried it like in the following code, but obviously, it did not work because there was the call off a.foo2() in between.

class SomeTests( unittest.TestCase ):
    def test_callOrder( self ):
        aMock = Mock()
        bMock = Mock()
        topMock = Mock()
        topMock.attach_mock( aMock, 'a' )
        topMock.attach_mock( bMock, 'b' )

        c = C()
        c.func( aMock, bMock )    

        expectedCalls = []
        expectedCalls.append( call.a.foo() )
        expectedCalls.append( call.b.goo() )
        topMock.assert_has_calls( expectedCalls, any_order=False )

How can I ignore the call of a.foo2() and just focus assertion on a.foo() and b.goo()?

1 Answers

As there is no specific check for this, you have to do 2 tests: first check that both functions are called, then check that they are called in the correct order:

class SomeTests(unittest.TestCase):
    def test_callOrder(self):
        ...

        c = C()
        c.func(aMock, bMock)

        expectedCalls = [call.a.foo(), call.b.goo()]
        topMock.assert_has_calls(expectedCalls, any_order=True)
        self.assertGreater(topMock.mock_calls.index(call.b.goo()),
                           topMock.mock_calls.index(call.a.foo()))

The first call (assert_has_calls with any_order=True) will succeed if the functions are called at all, regardless of order and other calls in-between. The second check relies on the mock_calls property which allows for more checks, if there are no appropriate convenience functions.

Related