2017-01-03 4 views
0

Я хочу проверить свой модуль регистрации. У меня есть функция, которая генерирует строку и записывает ее в файл. У меня есть следующий код:Mock file stream in python

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) 

Я думал, что патч будет создать реальный объект, который я мог бы прочитать и проверить, если он записывает содержимое для FileStream как и ожидалось, вместо этого я получил:

AssertionError: <MagicMock name='open_file_stream.readline()' id='3066213676'> != 'abc' 

Как это исправить? Или, если содержимое находится в этом объекте MagicMock, как его прочитать?

ответ

0

Прежде всего, вы должны высмеять внешние ресурсы, а не свой собственный код. В этом случае open. Вы можете проверить открытие, используя mock_open из формата библиотеки mock.

Допустим, у вас есть этот код здесь в вашем 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') 

Таким образом, вы рассказываете питона, что во время выполнения теста , предположим, что существует новый метод 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 и т. Д., И вы можете протестировать, как пожелаете.

+0

Утверждение в последней строке не работает, когда применяется '' w'', но без него все работает. Благодаря! – thecoparyew