Karthikeyan Singaravelan <tir.kar...@gmail.com> added the comment:
I did some debugging with docstring for wraps. > `wraps`: Item for the mock object to wrap. If `wraps` is not None then > calling the Mock will pass the call through to the wrapped object > (returning the real result). Attribute access on the mock will return a > Mock object that wraps the corresponding attribute of the wrapped object > (so attempting to access an attribute that doesn't exist will raise an > `AttributeError`). > If the mock has an explicit return_value set then calls are not passed to > the wrapped object and the return_value is returned instead. So calling mock.Mock(wraps=c) sets the _mock_wraps with c. When we set m.func.side_effect and call m.func() it checks for the side_effect (func2) to be a callable and calls it [0]. It also checks if self._mock_wraps is not None which in this case is MyClass() and checks for the func of Myclass that is also called at [1] . As per the docstring since it wraps the actual object calling m.invalid_func without return_value set will cause attribute error like "AttributeError: 'MyClass' object has no attribute 'invalid_func'" It seems to be a general case with mock itself where when side_effect and return_value are set then side_effect is called and ignores the return_value set unless the side_effect returns the sentinel value DEFAULT as in test [2]. I find this to be surprising. $ ./python.exe Python 3.8.0a0 (heads/master:b7278736b3, Nov 28 2018, 10:26:47) [Clang 7.0.2 (clang-700.1.81)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> from unittest import mock >>> m = mock.Mock() >>> m.side_effect = lambda : 2 >>> m.return_value = 3 >>> m() # side_effect and return_value are set returning side_effect 2 >>> f = mock.Mock() >>> f.return_value = 3 >>> f() # side_effect is not set thus returns only return_value 3 As per the original report when there is a return_value set without the side_effect it returns the set return_value. When there is a return_value set with the side_effect then return value of the side effect is returned though return_value is explicitly set like above also with wraps >>> m = mock.Mock(wraps=c) >>> print(m.func()) func called 1 >>> m.func.return_value = 3 >>> print(m.func()) 3 >>> f = mock.Mock(wraps=c) >>> f.func.side_effect = func2 >>> f.func.return_value = 3 >>> print(f.func()) func2 called 2 [0] https://github.com/python/cpython/blob/bde9d6bbb46ca59bcee5d5060adaa33c3ffee3a6/Lib/unittest/mock.py#L1031 [1] https://github.com/python/cpython/blob/bde9d6bbb46ca59bcee5d5060adaa33c3ffee3a6/Lib/unittest/mock.py#L1041 [2] https://github.com/python/cpython/blob/54ba556c6c7d8fd5504dc142c2e773890c55a774/Lib/unittest/test/testmock/testmock.py#L156 ---------- nosy: +mariocj89, michael.foord _______________________________________ Python tracker <rep...@bugs.python.org> <https://bugs.python.org/issue35330> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com