def time_of_day(): return datetime.datetime.utcnow().strftime('%H:%M:%S')
@unittest.patch('datetime.datetime.utcnow') def test_handle_leap_second(self, utcnow_mock): utcnow_mock.return_value = datetime.datetime( year=2015, month=6, day=30, hour=23, minute=59, second=60) actual = time_of_day() expected = '23:59:60' self.assertEquals(actual, expected)
The problem here (apart from Python not handling leap seconds) is that the test code assumes that
utcnow will return a
datetime.datetime object in absolutely all situations. That may be true right now for this specific function with the current interpreter etc., but if the return type changes for whatever reason the test will be passing when it probably should be failing. So for a robust test suite it would be better to guarantee that the mock return value has the same class as the original function return value. This is obviously only possible in languages where the return type is enforced by the compiler or interpreter. You could work around this by modifying a return value of the original function rather than creating your own:
utcnow_mock.return_value = datetime.datetime.utcnow().replace( year=2015, month=6, day=30, hour=23, minute=59, second=60)
Now we're operating with a different set of assumptions:
replacemodifies the object returned by
utcnowrather than returning some different object. This will not be an issue if the relevant object properties are writable.
utcnowalways returns objects with the same class.
Which method is more likely to produce a robust test suite? Please consider that unlike this example creating and then modifying an object may be simpler than creating it with the correct properties from scratch.