classification
Title: side_effect mocked method lose reference to instance
Type: enhancement Stage:
Components: Library (Lib) Versions: Python 3.8, Python 3.7
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: Adnan Umer, cjw296, mariocj89, remi.lapeyre, xtreak
Priority: normal Keywords:

Created on 2018-12-24 15:19 by Adnan Umer, last changed 2019-02-14 18:04 by xtreak.

Messages (3)
msg332463 - (view) Author: Adnan Umer (Adnan Umer) Date: 2018-12-24 15:19
When a method/bounded function is mocked and side_effect is supplied to it, the side_effect function doesn't get the reference to the instance.

Suppose we have something like this


class SomeClass:
    def do_something(self, x):
        pass

def some_function(x):
    cls = SomeClass()
    y = class.do_something(x)
    return y


And the test for some_function will be 


def do_something_side_effect(x):
    retrun x

def test_some_function():
    with mock.path("SomeCass.do_something") as do_something_mock:
        do_something_mock.side_effect = do_something_side_effect
        assert some_function(1)


Here do_something_side_effect mock will not have access to SomeClass instance.
msg332848 - (view) Author: RĂ©mi Lapeyre (remi.lapeyre) * Date: 2019-01-02 00:41
Is there a problem with:

from unittest import mock

class SomeClass:
    def do_something(self, x):
        pass

def some_function(x):
    obj = SomeClass()
    y = obj.do_something(x)
    return y

def do_something_side_effect(self, x):
    print(self)
    return x

def test_some_function():
    with mock.patch.object(SomeClass, "do_something", do_something_side_effect):
        assert some_function(1)

?
msg335548 - (view) Author: Karthikeyan Singaravelan (xtreak) * (Python committer) Date: 2019-02-14 18:04
Thanks for the report. I think this is design by choice that self is not passed to the side_effect directly set on the mock [0]. Changing this would break existing tests like [1] . You can use the approach by @remi.lapeyre which directly replaces the function on the target inside the context manager at [2] passing self to the side_effect callable.

[0] https://github.com/python/cpython/blob/8a1657b93469580ef345c7c91738587f3d76e87d/Lib/unittest/mock.py#L1043
[1] https://github.com/python/cpython/blob/8a1657b93469580ef345c7c91738587f3d76e87d/Lib/unittest/test/testmock/testmock.py#L664
[2] https://github.com/python/cpython/blob/8a1657b93469580ef345c7c91738587f3d76e87d/Lib/unittest/mock.py#L1376
History
Date User Action Args
2019-02-14 18:04:09xtreaksetnosy: + cjw296, xtreak, mariocj89

messages: + msg335548
versions: - Python 2.7, Python 3.4, Python 3.5, Python 3.6
2019-01-02 00:41:13remi.lapeyresetnosy: + remi.lapeyre
messages: + msg332848
2018-12-24 15:19:00Adnan Umercreate