I've got an Alarm object that uses a Sensor object. In my test I'd like to patch Sensor with a Stub. The code below works, but I have to explicitly pass in the stub to the Alarm constructor:
#tire_pressure_monitoring.py from sensor import Sensor class Alarm: def __init__(self, sensor=None): self._low_pressure_threshold = 17 self._high_pressure_threshold = 21 self._sensor = sensor or Sensor() self._is_alarm_on = False def check(self): psi_pressure_value = self._sensor.sample_pressure() if psi_pressure_value < self._low_pressure_threshold or self._high_pressure_threshold < psi_pressure_value: self._is_alarm_on = True @property def is_alarm_on(self): return self._is_alarm_on #test_tire_pressure_monitoring.py import unittest from unittest.mock import patch, MagicMock, Mock from tire_pressure_monitoring import Alarm from sensor import Sensor class AlarmTest(unittest.TestCase): def test_check_with_too_high_pressure(self): with patch('tire_pressure_monitoring.Sensor') as test_sensor_class: test_sensor_class.instance.sample_pressure.return_value=22 alarm = Alarm(sensor=test_sensor_class.instance) alarm.check() self.assertTrue(alarm.is_alarm_on) What I'd like to do, but can't seem to find a way to achieve, is to replace the Sensor instance with a stub, without passing anthing to the Alarm constructor. This code looks to me like it should work, but doesn't:
def test_check_with_too_high_pressure(self): with patch('tire_pressure_monitoring.Sensor') as test_sensor_class: test_sensor_class.instance.sample_pressure.return_value=22 alarm = Alarm() alarm.check() self.assertTrue(alarm.is_alarm_on) The Alarm instance gets an instance of MagicMock, but the 'sample_pressure' method doesn't return 22. Basically I want to know if there is a way to use unittest.mock to test the Alarm class without needing a constructor that takes a Sensor instance as argument.