Python unittest: to mock.patch() or just replace method with Mock?
Question: When mocking classes or methods when writing unittests in Python, why do I
need to use
[@patch](http://www.voidspace.org.uk/python/mock/patch.html#mock.patch)
decorator? I just could replace the method with Mock object without any patch
annotation.

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)
    

**Could someone produce an example, where patch decorator is good and
replacing is bad?**

We have always used patch decorator with our team, but after reading [this
comment](http://mauveweb.co.uk/posts/2014/09/every-mock-patch-is-a-little-
smell.html#comment-1573595883) for a post, I got the idea that maybe we could
write nicer-looking code without the need of patch decorators.

I understand that patching is temporary, so maybe with some cases, it is
dangerous to not use patch decorator and replace methods with mock instead?
Could it be that replacing objects in one test method can affect the result of
the next test method?

I tried to prove this, but came up empty: both tests pass in the next 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


Answer: `patch.object` will restore the item you patched to its original state after
the test method returns. If you monkey-patch the object yourself, you need to
restore the original value if that object will be used in another test.

In your two examples, you are actually patching two different things. Your
call to `patch.object` patches the _class_ `FooBar`, while your monkey patch
patches a specific _instance_ of `FooBar`.

Restoring the original object isn't important if the object will be created
from scratch each time. (You don't show it, but I assume `self.foobar` is
being created in a `setUp` method, so that even though you replace its
`_get_foo` method, you aren't reusing that _specific_ object in multiple
tests.)

