Python mocked side effect is returning a mocked object instead of the value
Asked Answered
S

1

6

I did some research on side effects and as I understand it it's supposed to have the values pulled from an iterable on each call. But I'm not sure why it's not printing 1, 2 but instead

<MagicMock name='bar' id='4448537616'>
<MagicMock name='bar' id='4448537616'>
class Foo():
    def __init__(self):
        self.bar = 'foo'
        pass

from unittest import mock

def test_foo():
    f = Foo()
    with mock.patch.object(f, 'bar', side_effect=[1,2]) :
        print(f.bar)
        print(f.bar)

test_foo()

But if I do f.bar() I get the actual value, but bar is supposed to be an attribute not a function.

Is my understanding of how side_effects work incorrect?

Schuyler answered 3/8, 2021 at 18:45 Comment(2)
Did you find the solution to this? Im running into the exact same problem, and I cant seem to get a straight answer. The only difference is that Im trying to mock a function which changes its return value depending on the arguments.Reggie
Same issue for me, not returning correct valuePostern
L
1

As you said it yourself, side_effect is "supposed to have the values pulled from an iterable on each call". The keywords here are "on each call".

mock.patch.object(f, 'bar', side_effect=[1,2]) makes f.bar a mock object with a side effect that makes f.bar return the next value from [1,2] on each call, and by call it means to call f.bar with parentheses, f.bar().

To achieve your desired behavior of making f.bar itself return a different value on each access (not call), you can temporarily make Foo.bar a property instead, with the getter function being a mock object with a side effect of [1, 2].

Since Foo.bar is not predefined in your code, and mock.patch.object can only patch an existing attribute, you would have to manage the lifecycle of this mock Foo.bar yourself by creating and deleting it explicitly:

class Foo():
    def __init__(self):
        self.bar = 'foo'
        pass

from unittest import mock

def test_foo():
    Foo.bar = property(mock.Mock(side_effect=[1, 2]), mock.Mock())
    f = Foo()
    print(f.bar)
    print(f.bar)
    del Foo.bar

test_foo()

This outputs:

1
2

Demo: https://ideone.com/apXG5m

Lax answered 6/2, 2024 at 8:42 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.