我想测试我的日志记录模块。我有一个生成一行并将其写入文件的函数。我有以下代码:
def open_file_stream(filename, opt):
return open(filename, opt)
def close_file_stream(f):
f.close()
def write_line_to_log_file(message, pid, module, state, data={}, datatype='AKV'):
file_path = '/path/to/file'
try:
f = open_file_stream(file_path, 'a')
# generate_line only takes the arguments and formats it to string
f.write(generate_line(message, pid, module, state, data, 'AKV') + '\n')
except Exception as e:
raise RuntimeError('Failed to write log line to %s: %s' % (file_path, str(e)))
finally:
f.close()
我尝试使用以下代码测试函数write_line_to_log_file
:
class Unit_test(unittest.TestCase):
@patch('my_logger.generate_line', return_value='abc')
def test_write_line_to_log_file(self, arg1):
with patch('my_logger.open_file_stream', return_value=StringIO.StringIO()) as f:
my_logger.write_line_to_log_file(message='message123', pid=1234,
module='abc/def', state='OK',
data={'test_key': 'test_value'})
should_be = 'abc'
f.seek(0)
self.assertEqual(f.readline(), should_be)
我认为该补丁会创建我可以阅读的真实对象,并检查它是否按预期将内容写入文件流,而不是我得到:
AssertionError: <MagicMock name='open_file_stream.readline()' id='3066213676'> != 'abc'
我该如何解决这个问题?或者,如果内容位于此MagicMock
对象中,我该如何阅读?
答案 0 :(得分:0)
首先,你应该模拟外部资源而不是你自己的代码。
在这种情况下open
。您可以使用mock库格式的mock_open
来测试打开。
假设您在my_module.py
def write_contents(contents):
try:
with open('/my/path', 'w') as fh:
fh.write(contents)
except IOError:
print "Something wrong happened"
您可以使用mock_open
进行以下测试用例import mock
import unittest
import my_module
class TestClass(unittest.TestCase):
def test_my_module(self):
m = mock.mock_open()
with mock.patch('my_module.open', m, create=True) as mocked_open:
contents = "Sample write content"
my_module.write_contents(contents)
file_handle = mocked_open()
# Do the assert
file_handle.write.assert_called_once_with(contents, 'w')
这样你告诉python在测试运行期间,假设存在一个新的open
方法,并断言它的行为符合预期。
当你执行with patch('my_logger.open_file_stream', return_value=StringIO.StringIO()) as f:
时,f是一个模拟对象,它只包含你添加的东西,即通过赋予return_value属性或给它一个side_effect。
您可以将上述示例调整为您的案例。 file_handle
对象的行为与任何其他open
对象类似,使用write
,read
,readinto
等方法,您可以根据需要进行测试