mockito-python icon indicating copy to clipboard operation
mockito-python copied to clipboard

How to verify stubbed methods (from different mocks) are called in order?

Open ghost opened this issue 2 years ago • 5 comments

Hello,

I didn’t find this information in the documentation, so how would I achieve that?

E.g. Makes sure that this passes:

verify(self._subscriber1, times=1).run('data')
verify(self._subscriber2, times=1).run('data')
verify(self._subscriber3, times=1).run('data')

but this fails

verify(self._subscriber3, times=1).run('data')
verify(self._subscriber2, times=1).run('data')
verify(self._subscriber1, times=1).run('data')

Thank you

ghost avatar Dec 10 '22 19:12 ghost

That's not implemented. inorder.verify is for one mock or mocked object. There is no global storage for invocations, so we don't have this information at hand.

kaste avatar Dec 10 '22 21:12 kaste

I used code like this in the past:

def test():
    message = []
    def record_message(message):
        messages.append(message)

    when(subscriber1).run(msg).thenAnswer(record_message)

If that works:

	patch(subscriber1, recordMessage)  # instead of `when...thenAnswer` may read better

kaste avatar Dec 11 '22 07:12 kaste

From thousands of tests, that is really the first time I would like to test that, because in my observer implementation, order of execution is essential.

I guess I could record calls myself in an ordered list as you suggest and verify afterwards.

Thanks @kaste.

ghost avatar Dec 14 '22 18:12 ghost

Hi @gui-don , can you please provide a code snippet demonstrating the complete flow? I think this might also be interesting as a recipe in the docs.

stevenengland avatar Apr 08 '23 18:04 stevenengland

Hi @stevenengland,

I solved this in a non-generic way. I used the "stop_propagation" pattern to test order in my case.

Given these mocks:

[…]
self._subscriber_x = mock(EventSubscriber)
when(self._subscriber_x).get_order().thenReturn(2)
when(self._subscriber_x).must_stop_propagation().thenReturn(False)

[…]
self._subscriber_stop = mock(EventSubscriber)
when(self._subscriber_stop).get_order().thenReturn(1)
when(self._subscriber_stop).must_stop_propagation().thenReturn(True)

And the subject I’m testing, where order is important:

self._subject = MyEventDispatcher(subscribers=[…])

Then just:


self._subject.register(self._subscriber_stop)

verify(self._subscriber_stop, times=1).run('data')
verify(self._subscriber2, times=0).run(...)
[…]

verifyNoMoreInteractions()

If order of my subject was not working, then other subscribers besides the subscriber_stop would be called. I do not think it’s worth documenting. It does work here, thanks to must_stop_propagation(), a wanted feature. I don’t think people are gonna create public methods just to test their code :(

ghost avatar Jun 19 '23 01:06 ghost