Python unittest: to mock.patch () or just replace a method with mock?

When confusing classes or methods when writing unittests in Python, why should I use @patch decorator? I can simply replace the method with a Mock object without annotating the patches.

Examples:

class TestFoobar(unittest.TestCase): def setUp(self): self.foobar = FooBar() # 1) With patch decorator: @patch.object(FooBar, "_get_bar") @patch.object(FooBar, "_get_foo") def test_get_foobar_with_patch(self, mock_get_foo, mock_get_bar): mock_get_bar.return_value = "bar1" mock_get_foo.return_value = "foo1" actual = self.foobar.get_foobar() self.assertEqual("foo1bar1", actual) # 2) Just replacing the real methods with Mock with proper return_value: def test_get_foobar_with_replacement(self): self.foobar._get_foo = Mock(return_value="foo2") self.foobar._get_bar = Mock(return_value="bar2") actual = self.foobar.get_foobar() self.assertEqual("foo2bar2", actual) 

Can someone give an example where fixing the patch is good and replacing it is bad?

We always used a patch decorator with our team, but after reading this comment for publication, I had the idea that, perhaps, we could write more beautiful code without the need to fix the patches.

I understand that the fix is ​​temporary, so it may be dangerous in some cases not to use patch fix and replace methods instead? Maybe replacing objects in one test method can affect the result of the next test method?

I tried to prove it, but came up empty: both tests pass in the following code:

 def test_get_foobar_with_replacement(self): self.foobar._get_foo = Mock(return_value="foo2") self.foobar._get_bar = Mock(return_value="bar2") actual = self.foobar.get_foobar() self.assertIsInstance(self.foobar._get_bar, Mock) self.assertIsInstance(self.foobar._get_foo, Mock) self.assertEqual("foo2bar2", actual) def test_get_foobar_with_real_methods(self): actual = self.foobar.get_foobar() self.assertNotIsInstance(self.foobar._get_bar, Mock) self.assertNotIsInstance(self.foobar._get_foo, Mock) self.assertIsInstance(self.foobar._get_bar, types.MethodType) self.assertIsInstance(self.foobar._get_foo, types.MethodType) self.assertEqual("foobar", actual) 

Full source code (Python 3.3): dropbox.com/s/t8bewsdaalzrgke/test_foobar.py?dl=0

+7
python decorator unit-testing mocking
source share
1 answer

patch.object restore the item that you fixed to its original state after the test method returned. If you neutralize the object yourself, you need to restore the original value if this object will be used in another test.

In your two examples, you are actually fixing two different things. Your call to patch.object corrects the FooBar class, while your monkey patch fixes a specific instance of FooBar .

Restoring the original object does not matter if the object is created from scratch every time. (You do not show it, but I assume that self.foobar is created in the setUp method, so even if you replace its _get_foo method, you won’t reuse this particular object in several tests.)

+4
source share

All Articles