A mock will let you call any method or read any attribute, even if it doesn’t exist.
>>> x = Mock() >>> wtf = x.wtf() >>> type(wtf) <class 'unittest.mock.Mock'> >>> wtf2 = x.wtf() >>> wtf == wtf2 True
The returned values are consistent across references.
>>> omai = x.omai >>> type(omai) <class 'unittest.mock.Mock'> >>> omai2 = x.omai >>> omai == omai2 True
If you assign a value to an attribute, the mock is replaced.
>>> x.omai = 'replacement' >>> x.omai 'replacement'
Mocked functions return mocks. They always return the same value.
>>> wtf() == wtf() True >>> wtf() == wtf2() True
You can replace the return value. The backing mock is a singleton, so it is updated everywhere.
>>> wtf.return_value = 666 >>> wtf() 666 >>> wtf2() 666
Mock names are auto-generated and can be used to see how the mock was created/referenced.
>>> y = Mock() >>> y <Mock id='140403021814864'> >>> y.hello <Mock name='mock.hello' id='140402753195408'> >>> y.hello.shirley <Mock name='mock.hello.shirley' id='140402618536016'> >>> y.hello().shirley.what.are.you().doing <Mock name='mock.hello().shirley.what.are.you().doing' id='140402754691600'>
You can restrict the mock to specific attributes with
>>> z = Mock(spec=['color', 'flavor', 'diarrhea']) >>> z.color <Mock name='mock.color' id='140402618331216'> >>> z.flavor <Mock name='mock.flavor' id='140402485559120'> >>> z.diarrhea <Mock name='mock.diarrhea' id='140402618142224'> >>> z.horse_sense Traceback (most recent call last): File "<input>", line 1, in <module> z.horse_sense File "/opt/anaconda3/envs/pi/lib/python3.7/unittest/mock.py", line 599, in __getattr__ raise AttributeError("Mock object has no attribute %r" % name) AttributeError: Mock object has no attribute 'horse_sense'
Mocks do not have dunder methods.
>>> a = Mock() >>> with a as a_context: ... print(a_context) ... ... Traceback (most recent call last): File "<input>", line 1, in <module> with a as a_context: AttributeError: __enter__ >>> b = Mock() >>> b.__enter__ = Mock() >>> b.__exit__ = Mock() >>> with b as b_context: ... print(b_context) ... ... <Mock name='mock.__enter__()' id='140402757814160'>
MagicMocks do have dunder methods.
>>> c = MagicMock() >>> with c as c_context: ... print(c_context) ... ... <MagicMock name='mock.__enter__()' id='140402757693904'>