Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python patch decorator spilling into other methods

My understanding is that when you use a patch decorator on a unit test (I'm using nose framework), the scope of that patch decorator is the scope of the test case. Here's the issue:

@patch('a')
@patch('b')
@patch('b')
def test_add_stuff(self, mock_a, mock_b, mock_c):
    url = '/path/blah/blah'
    assert_true(stuff)
    # Now those three patch decorators should be "done"


def test_delete_stuff(self):
    url = '/another_path/not_important'
    assert_true(something)

In my second test case, test_delete_stuff, I have added a print statement in the actual code in an effort to debug an error that was being thrown. Turns out, one of the function calls within the controller action being hit through the url is returning a MagicMock object! It's mock_b from the previous test case.

If I simply reverse the order of the two test cases, nothing changes. If I comment out the one with the patch decorators, my second test case passes.

Additional info: There are no patch decorators on the class that these instance methods are under.

Any ideas?

--UPDATE--

It turns out that I didn't mock my function calls from where they were being looked up, and that fixed the issue. However, it does not explain why the scope of the patch exceeded the one test case.

If the controller gets instantiated only when the GET request gets sent using app.get, and the imports in the controller file get mocked, why would the MagicMock object persist through multiple unit tests?

like image 216
Bowser Avatar asked Oct 17 '14 19:10

Bowser


1 Answers

I guess the issue with the path scope has appeared, because you patched methods in the TestCase class. You can find in the official Python unittest.patch documentation:

Patch can be used as a TestCase class decorator. It works by decorating each test method in the class. This reduces the boilerplate code when your test methods share a common patchings set. patch() finds tests by looking for method names that start with patch.TEST_PREFIX. By default this is 'test', which matches the way unittest finds tests. You can specify an alternative prefix by setting patch.TEST_PREFIX.

So all the methods with the prefix test will be decorated with the patches. This is the default behavior.

like image 54
Max Voitko Avatar answered Nov 20 '22 02:11

Max Voitko