Python:模拟上下文管理器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28850070/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 03:49:44  来源:igfitidea点击:

Python: Mocking a context manager

pythonmocking

提问by Willem

I don't understand why I can't mock NamedTemporaryFile.name in this example:

我不明白为什么我不能在这个例子中模拟 NamedTemporaryFile.name :

from mock import Mock, patch
import unittest
import tempfile

def myfunc():
    with tempfile.NamedTemporaryFile() as mytmp:
        return mytmp.name

class TestMock(unittest.TestCase):
    @patch('tempfile.NamedTemporaryFile')
    def test_cm(self, mock_tmp):
        mytmpname = 'abcde'
        mock_tmp.__enter__.return_value.name = mytmpname
        self.assertEqual(myfunc(), mytmpname)

Test results in:

测试结果:

AssertionError: <MagicMock name='NamedTemporaryFile().__enter__().name' id='140275675011280'> != 'abcde'

采纳答案by Michele d'Amico

You are setting the wrong mock: mock_tmpis not the context manager, but instead returnsa context manager. Replace your setup line with:

您设置了错误的模拟:mock_tmp不是上下文管理器,而是返回一个上下文管理器。将您的设置行替换为:

mock_tmp.return_value.__enter__.return_value.name = mytmpname

and your test will work.

并且您的测试将起作用。

回答by Peter K

Here is an alternative with pytestand mocker fixture, which is a common practice as well:

这是pytestmocker fixture的替代方案,这也是一种常见做法:

def test_myfunc(mocker):
    mock_tempfile = mocker.MagicMock(name='tempfile')
    mocker.patch(__name__ + '.tempfile', new=mock_tempfile)
    mytmpname = 'abcde'
    mock_tempfile.NamedTemporaryFile.return_value.__enter__.return_value.name = mytmpname
    assert myfunc() == mytmpname

回答by hmobrienv

Extending Peter K's answer using pytest and the mocker fixture.

使用 pytest 和模拟装置扩展 Peter K 的答案。

def myfunc():
    with tempfile.NamedTemporaryFile(prefix='fileprefix') as fh:
        return fh.name


def test_myfunc(mocker):
    mocker.patch('tempfile.NamedTemporaryFile').return_value.__enter__.return_value.name = 'tempfilename'
    assert myfunc() == 'tempfilename'