10

I am testing a class that needs a mock in the constructor, so I usually do this:

class TestActionManager(unittest.TestCase):
    @patch('actionlib.SimpleActionClient', return_value=create_autospec(actionlib.SimpleActionClient))
    def setUp(self, mock1):
        self.action_manager = ActionManager()

Then in this class I add all the tests. So the first one is working fine

    def test_1(self):
        self.action_manager.f()
        self.action_manager.f.assert_called_once()

But if I add another test and run both

    def test_2(self):
        self.action_manager.f()
        self.action_manager.f.assert_called_once()

It says f has been called twice. I was expecting setUp to create a new ActionManager (and hence create a new mock) before starting every test, but it is clearly not happening, since the mock is somehow shared. Also I tried to do

def tearDown(self):
    del self.action_manager

But it does not fix the problem.

I have read something related in Python Testing - Reset all mocks? where the solution is to use a different library (something that I would like to avoid)

and in Any way to reset a mocked method to its original state? - Python Mock - mock 1.0b1 where it is using different classes to do it.

Is there any possibility to reset the mock in the same class before or after every test?

Mogsdad
  • 44,709
  • 21
  • 151
  • 275
Bernat
  • 379
  • 1
  • 2
  • 12

1 Answers1

18

I believe what you're looking for is reset_mock

Here's, in general, how it works:

def test_1(self):
    f = MagicMock()  # or whatever you're mocking
    f()
    f.assert_called_once()
    f.reset_mock()
    f()
    f.assert_called_once()

The result will be PASSED

If you want to automate, then you store the mocked thing inside setUp, and in tearDown you call the mocked thing's .reset_mock() method.

def setUp(self, mock1):
    self.mock1 = mock1
    # ... do other things ...

def tearDown(self):
    self.mock1.reset_mock()
Mogsdad
  • 44,709
  • 21
  • 151
  • 275
pepoluan
  • 6,132
  • 4
  • 46
  • 76