A sick mock
written on Tuesday, October 16, 2012
You can mock too much sometimes...
class ParseReportTest(unittest.TestCase): @patch('__builtin__.open') def test_get_report_string(self, mock_open): mock_file, mock_context_manager = Mock(), Mock() mock_enter, mock_exit = Mock(), Mock() mock_open.return_value = mock_context_manager mock_file.read.return_value = sentinel.file_contents mock_enter.return_value = mock_file setattr(mock_context_manager, '__enter__', mock_enter) setattr(mock_context_manager, '__exit__', mock_exit) quota_report = get_report_string() self.assertEqual(quota_report, sentinel.file_contents) self.assertEqual(mock_open.call_args_list, [call('/srv/report')])
I thought this was pretty interesting. It is the first time I have tried to mock a built in context manager. In some situations would probably be the only solution. But in this instance mocking a constant made more sense. So I ended up replacing it with:
@patch('anywhere.files.management.commands.warn_about_quotas.QUOTA_REPORT_LOCATION') def test_get_report_string(self, mock_location): fh, temp_report_path = mkstemp() mock_location = temp_report_path fh.write(QUOTA_TEST_DATA) quota_report = get_report_string() self.assertEqual(quota_report, QUOTA_TEST_DATA) os.remove(temp_report_path)
Anyway, it was still interesting to learn how to mock a built in context manager. Figuring out how to refer to the right object was worth it all by itself.