使用mock_open修补功能在哪里出错?

时间:2019-08-15 20:38:44

标签: python unit-testing python-unittest

我有一个函数,该函数调用一个子函数来打开文件。我正在尝试测试父函数,但是我想修补子函数并使它返回我传入的数据(就像它从文件中读取一样)。

tests.py

# Read in the sample data
__SAMPLE_LOG = os.path.join(settings.BASE_DIR, "apps/tests/log_viewer/sample_logs/sample_manager_log.log")
sample_data = []
for line in reversed_lines(open(__SAMPLE_LOG)):
    sample_data.append(line)

sample_data = ('').join(sample_data)

class ReadLog(TestCase):
    @patch('apps.log_viewer.utils.reversed_lines', new_callable = mock_open, read_data = sample_data)
    def test_returnsDictionaryContainingListOfDictionaries(self, mock_file):
        activity = read_log()

        # Make sure the sample data was read ==> this fails.
        self.assertEqual(open(settings.ACTIVITY_LOG_FILE).read(), sample_data)

utils.py

def read_log():

   # This is the line I am trying to patch
   for line in reversed_lines(open(settings.ACTIVITY_LOG_FILE)):      
      # process data

# see: https://stackoverflow.com/questions/260273/most-efficient-way-to-search-the-last-x-lines-of-a-file-in-python/260433#260433
def reversed_lines(file):
    "Generate the lines of file in reverse order."
    part = ''
    for block in reversed_blocks(file):
        for c in reversed(block):
            if c == '\n' and part:
                yield part[::-1]
                part = ''
            part += c
    if part: yield part[::-1]

def reversed_blocks(file, blocksize=4096):
    "Generate blocks of file's contents in reverse order."
    file.seek(0, os.SEEK_END)
    here = file.tell()
    while 0 < here:
        delta = min(blocksize, here)
        here -= delta
        file.seek(here, os.SEEK_SET)
        yield file.read(delta)

错误

我正在尝试通过reversed_lines()方法修补utils.pyread_log()的{​​{1}},但是read_log()仍从实际日志中读取,表明我没有修补{{ 1}}正确。

当我改变

reversed_lines()

@patch('apps.log_viewer.utils.reversed_lines', new_callable = mock_open, read_data = sample_data)

我明白了

@patch('builtins.open', new_callable = mock_open, read_data = sample_data)

我要去哪里错了?

1 个答案:

答案 0 :(得分:2)

以下是https://docs.python.org/3.3/library/unittest.mock.html#mock-open文档中的示例,我想你是

@patch('builtins.open', mock_open(read_data = sample_data), create=True)

但是请仔细阅读mock_open的来源:https://github.com/python/cpython/blob/3.7/Lib/unittest/mock.py#L2350

该文件句柄的tell方法似乎不是由该模拟实现的。唯一受支持的方法是readreadlinereadlineswrite并遍历内容。您需要手动为tell方法设置模拟。这不是一般的实现,但可以在您的特定情况下使用:

class ReadLog(TestCase):
    @patch('builtins.open', mock_open(read_data = sample_data), create=True)
    def test_returnsDictionaryContainingListOfDictionaries(self, mock_file):
        mock_file.return_value.tell.return_value = len(sample_data)
        ...