I am trying to mock a coroutine. As such, this mock's __next__() and close() are called. While mocking close() works, I cannot mock __next__():
mock_coroutine = mock.Mock()
mock_coroutine.some_call(1, 2, 3)
mock_coroutine.some_call.assert_called_with(1, 2, 3)
mock_coroutine.close()
mock_coroutine.close.assert_called_with()
#this fails
mock_coroutine.__next__()
mock_coroutine.__next__.assert_called_with()
What am I missing? How to make sure my mock's __next__() method is called?
For now, I am using the following:
class MockCoroutine:
def __next__(self):
self.called_next = True
def close(self):
self.called_exit = True
However, I very much rather use a standard mock.
You need to use MagicMock, not Mock, to have magic methods like __next__ available by default:
>>> from unittest import mock
>>> mock_coroutine = mock.MagicMock()
>>> mock_coroutine.__next__()
<MagicMock name='mock.__next__()' id='4464126552'>
>>> mock_coroutine.__next__.assert_called_with()
Quoting from the documentation:
Mockallows you to assign functions (or otherMockinstances) to magic methods and they will be called appropriately. TheMagicMockclass is just aMockvariant that has all of the magic methods pre-created for you (well, all the useful ones anyway).
So, alternatively, you could still use the regular Mock object, but then you need to explicitly add that attribute:
>>> mock_coroutine = mock.Mock()
>>> mock_coroutine.__next__ = mock.Mock()
>>> mock_coroutine.__next__()
<Mock name='mock.__next__()' id='4464139232'>
That's because although Mock creates attributes on the fly as you access them, any attributes with leading and trailing underscores are explicitly exempted from that. See this footnote:
The only exceptions are magic methods and attributes (those that have leading and trailing double underscores). Mock doesn’t create these but instead raises an
AttributeError. This is because the interpreter will often implicitly request these methods, and gets very confused to get a new Mock object when it expects a magic method. If you need magic method support see magic methods.
But note that the magic methods are usually meant to be looked up on the class, not the instance, so directly adding the __next__ attribute to a Mock instance can still fail; the MagicMock class takes care of this specific issue for you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With