0

I am unit testing a single line of code within an if statement where I append an item onto a list if a variable has a specific value.

foo = []
if bar == 'a':
    foo.append(bar)

I would like to assert that such an append has been called. I have patched methods from a variety of sources before, but not methods belonging to basic Python data types. What class would I specify as the path for the mock.patch decorator?

@mock.patch('append')
def test_appends_bar_to_foo(mock_append):
    assert mock_append.called

With the above code, I get TypeError: Need a valid target to patch. You supplied: 'append'

nerdenator
  • 1,265
  • 2
  • 18
  • 35
  • Why not just leave `append` alone and have your test look at the list to see if the item got appended? – Samwise May 30 '23 at 03:53
  • I think that is too low-level (you're testing the implementation detail). It would be better to test the contents of the list, you could e.g. change `foo.append(bar)` to `foo += [bar]` without failing the test. – wim May 30 '23 at 03:53
  • @Samwise the list `foo` in this case is not the thing returned in the larger function; it is something used to decide what the function return will be. – nerdenator May 30 '23 at 04:05
  • 1
    That has the problem that wim pointed out where you're testing something that's internal to the function, rather than what the function actually does. Maybe you could break the logic that builds the `foo` list out into its own function so that it can be tested on its own? – Samwise May 30 '23 at 05:01
  • 99.9% sure this is an [XY Problem](https://xyproblem.info/). There is no conceivable scenario where you would need to mock the `list.append` method in any unit test. If you provide additional context for why you think you need that, we can try to figure out a different approach. – Daniil Fajnberg Jun 01 '23 at 21:44

1 Answers1

1

You can patch foo instead and assert that its append method has been called:

foo = []
with mock.patch('__main__.foo') as mock_foo:
    foo.append(1)
    mock_foo.append.assert_called() # assertion success
blhsing
  • 91,368
  • 6
  • 71
  • 106
  • would i replace `__main__` with the function that `foo` is in? – nerdenator May 30 '23 at 03:55
  • There is no way you can patch a local variable of a function from the outside. Consider rewriting the function so that `foo` is exposed as an argument instead. – blhsing May 30 '23 at 04:13