0

So lately in Python I started using the unittest library. However, one thing that I cannot understand (and I've tried looking this up for hours and hours...) is why you would use the patch decorator over an explicit MagicMock objects.

To be more specific, below is my code that I am attempting to test. Some quick notes:

  • The code is attempting to test a simple menu class for some restaurant.

  • In the setUp method, I am preparing the instantiated Menu object by storing some instantiated Food objects (which in this case are replaced by MagicMock objects).

  • In the testFindItem method, I am attempting to find and return a Food object from the menu via searching for it's name. Then I compare the found object with the Food object (MagicMock object in this case) it is suppose to be.

Now that being said, observe how in the setUp method I replaced self.bread and self.cardboard by MagicMock objects instead of Food objects. The code works, and that is great but an alternative would be to use a patch decorator that overrides the Food class.

TL;DR: Why would that (i.e. using a patch) be better or worse in this case? Or rather as mentioned before, why use patch decorator over explicit MagicMock objects?

Oh on a side note, the closest answer that I have found is another post which discusses the difference between patch and mock but not why you would use one over the other: Mocking a class: Mock() or patch()?

class MenuTest(unittest.TestCase):
"""
Unit test class for Menu class.
"""

def setUp(self):
    """
    Prepares a menu to be tested against using mock objects.
    """
    self.bread = MagicMock()
    self.cardboard = MagicMock()

    self.bread.name = "bread"
    self.cardboard.name = "cardboard"

    foodItems = [self.cardboard, self.bread]

    self.menu = Menu(foodItems)

def testFindItem(self):
    """
    Tests whether a specified food item can be found on the menu.
    """
    # Items on the menu

    self.assertEqual(self.menu.findItem("bread"), self.bread)
    self.assertEqual(self.menu.findItem("cardboard"), self.cardboard)

    # Items not on the menu
    with self.assertRaises(NameError):
        self.menu.findItem("salvation")
Community
  • 1
  • 1
OthmanEmpire
  • 103
  • 2
  • 7
  • 1
    You use patch when you're patching existing code, whereas you're just passing mocks as arguments. That's why you don't see a benefit; there isn't one. Have you considered reading the `mock` documentation? – jonrsharpe Feb 21 '16 at 14:36
  • @jonrsharpe Ah, I see. Also, If you are referring to here: https://docs.python.org/3/library/unittest.mock.html, then yes, many and many times but I still find it difficult to grasp it. – OthmanEmpire Feb 21 '16 at 15:36
  • I downvoted the question because, even it is correct and well written, it just create noise and doesn't give any good point to SO. This question can be summarized by "why I should use patch if I don't need it?". – Michele d'Amico Feb 22 '16 at 13:14
  • @Micheled'Amico Very well. I was hoping that the TL;DR statement would address that issue, perhaps not. Also, I wasn't aware that patch itself was not necessary until after Roseman's answer. – OthmanEmpire Feb 22 '16 at 18:14

1 Answers1

2

This isn't the use case for patch. The reason you use that is when you want to replace an object that is defined elsewhere. Here, you're explicitly instantiating the Menu and passing in the things you want to call assertions on, so patch is not useful; but there are plenty of times when the class under test creates its own objects, or gets them from other parts of the code, and that's when you'd use patch.

Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895