Python Mock - издевается над несколькими открытыми - PullRequest
6 голосов
/ 19 февраля 2012

После прочтения этого: Как мне смоделировать open, используемый в операторе with (используя платформу Mock в Python)?

Я могу смоделировать функцию open в pythonusing:

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' для старого текста и 'text2 'для newtext.

Как я могу это сделать?

Ответы [ 2 ]

5 голосов
/ 19 февраля 2012

Вот быстрый способ получить то, что вы хотите.Это немного обманывает, потому что два объекта файла в тестируемом методе - это один и тот же объект, и мы просто меняем возвращаемое значение вызова read после каждого чтения.Вы можете использовать одну и ту же технику в нескольких слоях, если хотите, чтобы файловые объекты были разными, но это будет довольно грязно и может излишне замаскировать цель теста.

Замените эту строку:

    m_file.read.return_value = 'text1'

с:

    reads = ['text1', 'text2']
    m_file.read.side_effect = lambda: reads.pop(0)
3 голосов
/ 19 февраля 2012

Возможно, хорошее возможное решение - это просто написать код так, чтобы его можно было легко протестировать.В случае 'diff' кажется достаточно легким (по общему признанию, не имеющим много другого контекста) иметь 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>

Будет ли это работать в вашем случае?

...