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:
Mock
allows you to assign functions (or otherMock
instances) to magic methods and they will be called appropriately. TheMagicMock
class is just aMock
variant 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