Я недавно узнал о unittest.monkey.patch
и его вариантах, и я хотел бы использовать его для модульного тестирования на атомарность функции чтения файла. Однако патч не имеет никакого эффекта.Как исправить метод io.RawIOBase.read с помощью unittest?
Вот моя настройка. Метод под наблюдением примерно вот так (abriged):
#local_storage.py
def read(uri):
with open(path, "rb") as file_handle:
result = file_handle.read()
return result
И модуль, который выполняет модульные тесты (также abriged):
#test/test_local_storage.py
import unittest.mock
import local_storage
def _read_while_writing(io_handle, size=-1):
""" The patch function, to replace io.RawIOBase.read. """
_write_something_to(TestLocalStorage._unsafe_target_file) #Appends "12".
result = io_handle.read(size) #Should call the actual read.
_write_something_to(TestLocalStorage._unsafe_target_file) #Appends "34".
class TestLocalStorage(unittest.TestCase):
_unsafe_target_file = "test.txt"
def test_read_atomicity(self):
with open(self._unsafe_target_file, "wb") as unsafe_file_handle:
unsafe_file_handle.write(b"Test")
with unittest.mock.patch("io.RawIOBase.read", _read_while_writing): # <--- This doesn't work!
result = local_storage.read(TestLocalStorage._unsafe_target_file) #The actual test.
self.assertIn(result, [b"Test", b"Test1234"], "Read is not atomic.")
Таким образом, патч должен гарантировать, что каждый раз, когда вы попробуйте прочитать его, файл будет изменен непосредственно перед и сразу после фактического чтения, как если бы это произошло одновременно, таким образом, проверяя атомарность нашего чтения.
В настоящее время удаленный тест работоспособности завершен, но я проверял с помощью операторов печати, что функция патча фактически не вызвана, поэтому файл никогда не получает дополнительных записей (он просто говорит «Тест»). Я также модифицировал код как неатомный.
Так что мой вопрос: Как я могу исправить функцию дескриптора ввода-вывода в модуле local_storage read
? Я читал в другом месте, что люди, как правило, заменяют функцию open(), чтобы возвращать что-то вроде StringIO
, но я не вижу, как это может решить эту проблему.
Мне нужно поддерживать Python 3.4 и выше.
вы смотрели, чтобы посмотреть, как издеваться 'open'? Прочтите [это] (http://www.voidspace.org.uk/python/mock/helpers.html#mock-open). Но иногда, да, я также видел, что 'StringIO' используется, чтобы не писать напрямую в файловую систему. – idjaw
В Python 3 он поддерживается [здесь] (https://docs.python.org/3/library/unittest.mock.html#mock-open) – idjaw
Я написал какое-то решение, которое объясняет, как справиться с контекстных менеджеров. Детали вокруг него не совсем связаны с тем, что вы пытаетесь сделать, но объясняют природу контекста и используют открытые. Надеюсь, что это поможет: http: // stackoverflow.com/a/33652204/1832539 – idjaw