0

While writing some tests today I came across a confusing behaviour:

Foo class definition:

class Foo:

    def bar(self, attrs):
        self._baz(attrs)
        attrs.pop('key')

    def _baz(self, attrs):
        pass

Foo class tests:

from unittest import TestCase, mock


class FooTestCase(TestCase):

    def test_bar(self):
        foo = Foo()
        attrs = {'key': 'value'}
        with mock.patch.object(foo, '_baz') as _baz_mock:
            # Copying `attrs` so that `foo.bar()` won't mutate it.
            foo.bar({**attrs})
        # Test fails here since `_baz_mock` gets called with `{}` (not sure why).
        _baz_mock.assert_called_once_with(attrs)

I expected _baz_mock.assert_called_once_with(attrs) to pass successfully since Foo.bar() performs attrs.pop('key') after calling self._baz(attrs), however it fails with the following AssertionError:

Expected call: _baz({'key': 'value'})
Actual call: _baz({})

Could someone please explain what is going on here and why _baz_mock gets called with {}?

Ernest
  • 2,799
  • 12
  • 28
  • 3
    I'm fairly certain that you'll find your answer here: https://stackoverflow.com/questions/40248075/how-do-we-ensure-that-the-calls-in-the-mock-call-args-list-contain-calls-with-ar. The fact that the pop takes place after the call does not matter. The same mutable object is mutated. – Ilja Everilä Jun 05 '18 at 11:55
  • @IljaEverilä Ah, I see. That makes sense though it's tricky. Thanks! – Ernest Jun 05 '18 at 12:09

0 Answers0