I need to fix three methods ( _send_reply , _reset_watchdog and _handle_set_watchdog ) using false methods before testing the fourth method call ( _handle_command ) in the unit test.
There are several ways to look at the documentation for the mock package:
With patch.multiple as a decorator
@patch.multiple(MBG120Simulator, _send_reply=DEFAULT, _reset_watchdog=DEFAULT, _handle_set_watchdog=DEFAULT, autospec=True) def test_handle_command_too_short_v1(self, _send_reply, _reset_watchdog, _handle_set_watchdog): simulator = MBG120Simulator() simulator._handle_command('XA99') _send_reply.assert_called_once_with(simulator, 'X?') self.assertFalse(_reset_watchdog.called) self.assertFalse(_handle_set_watchdog.called) simulator.stop()
With patch.multiple as a context manager
def test_handle_command_too_short_v2(self): simulator = MBG120Simulator() with patch.multiple(simulator, _send_reply=DEFAULT, _reset_watchdog=DEFAULT, _handle_set_watchdog=DEFAULT, autospec=True) as mocks: simulator._handle_command('XA99') mocks['_send_reply'].assert_called_once_with('X?') self.assertFalse(mocks['_reset_watchdog'].called) self.assertFalse(mocks['_handle_set_watchdog'].called) simulator.stop()
With multiple patch.object decorators
@patch.object(MBG120Simulator, '_send_reply', autospec=True) @patch.object(MBG120Simulator, '_reset_watchdog', autospec=True) @patch.object(MBG120Simulator, '_handle_set_watchdog', autospec=True) def test_handle_command_too_short_v3(self, _handle_set_watchdog_mock, _reset_watchdog_mock, _send_reply_mock): simulator = MBG120Simulator() simulator._handle_command('XA99') _send_reply_mock.assert_called_once_with(simulator, 'X?') self.assertFalse(_reset_watchdog_mock.called) self.assertFalse(_handle_set_watchdog_mock.called) simulator.stop()
Manual method replacement with create_autospec
def test_handle_command_too_short_v4(self): simulator = MBG120Simulator()
Personally, I think that the latter is the most readable for reading, and will not lead to terribly long lines if the number of mocking methods grows. It also avoids passing in simulator as the first ( self ) argument in assert_called_once_with .
But I do not find them particularly pleasant. The patch.object approach is especially repeated, which requires careful coordination of the order of parameters with nested decorations.
Is there any approach I skipped or a way to make this more readable? What do you do when you need to fix several methods in a test instance / class?