Python Mock - издевайтесь над несколькими открытыми
-
27-10-2019 - |
Вопрос
После прочтения этого: Как издеваться над открытием, используемым в операторе с оператором (используя макетную структуру в Python)?
Я могу издеваться над функцией открытой в Python, используя:
with patch(open_name, create=True) as mock_open:
mock_open.return_value = MagicMock(spec=file)
m_file = mock_open.return_value.__enter__.return_value
m_file.read.return_value = 'text1'
diffman = Diffman()
diffman.diff(path1, path2)
Это хорошо работает, когда мой тестируемый метод использовал один открытый оператор. Вот мой протестированный метод:
def diff(self, a, b):
with open(a, 'r') as old:
with open(b, 'r') as new:
oldtext = old.read()
newtext = new.read()
Значения OldText и NewText одинаковы ('Text1' здесь).
Я хотел бы иметь «Text1» для OldText и «Text2» для нового текста.
Как я могу это сделать ?
Решение
Вот быстрый способ получить то, что вы хотите. Он немного обманывает, потому что два объекта файла в тестируемом методе являются одним и тем же объектом, и мы просто изменяем возвращаемое значение вызова Read после каждого чтения. Вы можете использовать одну и ту же технику в нескольких слоях, если хотите, чтобы объекты файла были разными, но это будет довольно грязно, и это может замаскировать намерение теста без необходимости.
Замените эту линию:
m_file.read.return_value = 'text1'
с:
reads = ['text1', 'text2'] m_file.read.side_effect = lambda: reads.pop(0)
Другие советы
Возможно, хорошее возможное решение состоит в том, чтобы просто написать код таким образом, чтобы лучше поддаваться его легкому тестированию. В случае «diff» это кажется достаточно простым (не имея большого другого контекста, по общему признанию) иметь различие в качестве аргументов, уже открытых объектов файла. Это, вероятно, довольно небольшое изменение, которое нужно внести в код, и делает тестирование очень простым, поскольку затем вы можете легко предоставить фирменные файловые объекты в diff (), когда вы его тестируете, вместо того, чтобы пытаться прыгать через обручи, измешающиеся два экземпляра одинаковых встроенная функция как менеджер контекста, называемый внутри ... или что-то в этом роде ;-)
import StringIO
diff(a, b):
oldtext = a.read()
newtext = b.read()
def test_diff():
a = StringIO.StringIO('text1')
b = StringIO.StringIO('text2')
res = diff(a, b)
<some assertion here>
Будет ли это работать для вашего дела?