programing

(Python의 Mock 프레임워크를 사용하여)에서 사용되는 오픈을 어떻게 모킹합니까?

bestcode 2022. 11. 18. 21:39
반응형

(Python의 Mock 프레임워크를 사용하여)에서 사용되는 오픈을 어떻게 모킹합니까?

에서 다음 코드를 테스트하려면 어떻게 해야 하나요?

def testme(filepath):
    with open(filepath) as f:
        return f.read()

파이썬 3

프레임워크의 일부인 패치 및 사용.patch 콘텍스트 매니저로 사용되며 패치가 적용된 개체를 대체하기 위해 사용되는 개체를 반환합니다.

from unittest.mock import patch, mock_open
with patch("builtins.open", mock_open(read_data="data")) as mock_file:
    assert open("path/to/open").read() == "data"
mock_file.assert_called_with("path/to/open")

사용하고 싶은 경우patch데코레이터로서, 사용mock_open()의 결과로서new=에 대한 의론.patch조금 이상할 수도 있어요대신,patchnew_callable=그리고 모든 여분의 논쟁은 기억하라patchdoes not use는 에 전달됩니다.new_callable기능(매뉴얼에 기재되어 있습니다.

patch()는 임의의 키워드 인수를 사용합니다.이것들은, 에 건네집니다.Mock(또는 new_callable).

@patch("builtins.open", new_callable=mock_open, read_data="data")
def test_patch(mock_file):
    assert open("path/to/open").read() == "data"
    mock_file.assert_called_with("path/to/open")

이 경우 기억하십시오.patch는 조롱된 객체를 인수로 테스트 함수에 전달합니다.

파이썬 2

패치를 붙여야 합니다.__builtin__.open대신builtins.open그리고.mock의 일부가 아니다unittest, 당신은 할 필요가 있다.pip install를 개별적으로 Import 합니다.

from mock import patch, mock_open
with patch("__builtin__.open", mock_open(read_data="data")) as mock_file:
    assert open("path/to/open").read() == "data"
mock_file.assert_called_with("path/to/open")

이것을 하는 방법은 mock 0.7.0에서 변경되어 최종적으로 Python 프로토콜 메서드(매직 메서드)의 모킹(특히 MagicMock:

http://www.voidspace.org.uk/python/mock/magicmock.html

콘텍스트 매니저로서 오픈을 조롱하는 예(모크 문서의 예 페이지에서 참조):

>>> open_name = '%s.open' % __name__
>>> with patch(open_name, create=True) as mock_open:
...     mock_open.return_value = MagicMock(spec=file)
...
...     with open('/some/path', 'w') as f:
...         f.write('something')
...
<mock.Mock object at 0x...>
>>> file_handle = mock_open.return_value.__enter__.return_value
>>> file_handle.write.assert_called_with('something')

최신 버전의 mock을 사용하면 매우 유용한 mock_open helper를 사용할 수 있습니다.

mock_open(mock=없음, read_data=없음)

open 사용을 대체할 모크를 만드는 도우미 함수입니다.이 기능은 직접 호출된 오픈 콜에 대해 작동하거나 컨텍스트 매니저로 기능합니다.

mock 인수는 설정하는 모의 객체입니다.[None] (기본값)의 경우 MagicMock이 생성되며 API는 표준 파일핸들에서 사용할 수 있는 메서드 또는 속성으로 제한됩니다.

read_data는 파일핸들의 읽기 메서드를 반환하기 위한 문자열입니다.기본적으로는 빈 문자열입니다.

>>> from mock import mock_open, patch
>>> m = mock_open()
>>> with patch('{}.open'.format(__name__), m, create=True):
...    with open('foo', 'w') as h:
...        h.write('some stuff')

>>> m.assert_called_once_with('foo', 'w')
>>> handle = m()
>>> handle.write.assert_called_once_with('some stuff')

단순 파일에 mock_open을 사용하려면read()(이 페이지에서 이미 제공된 원래 mock_open 스니펫은 쓰기에 더 적합합니다.)

my_text = "some text to return when read() is called on the file object"
mocked_open_function = mock.mock_open(read_data=my_text)

with mock.patch("__builtin__.open", mocked_open_function):
    with open("any_string") as f:
        print f.read()

mock_open에 대한 문서에 따르면 이는 특히read()따라서 다음과 같은 일반적인 패턴에서는 작동하지 않습니다.for line in f,예를들면.

python 2.6.6 / mock 1.0.1 사용

맨 위의 답은 유용하지만 나는 그것을 조금 더 확장했다.

오브젝트의 ( 「 」 「 」 「 。fas f에.open()한 가지 방법은 다음과 같습니다.

def save_arg_return_data(*args, **kwargs):
    mm = MagicMock(spec=file)
    mm.__enter__.return_value = do_something_with_data(*args, **kwargs)
    return mm
m = MagicMock()
m.side_effect = save_arg_return_array_of_data

# if your open() call is in the file mymodule.animals 
# use mymodule.animals as name_of_called_file
open_name = '%s.open' % name_of_called_file

with patch(open_name, m, create=True):
    #do testing here

으로는 ★★★★★★★★★★★★★★★★★」open()하고 ""를 반환합니다.with를 호출합니다.__enter__()그 물건에 대해서.

을 제대로을 해야 .open()모조 오브젝트를 반환할 수 있습니다. 그 .__enter__()MagicMock( 「 Data Object」(「Mock Data/File」/「Mock Data/File」)가 됩니다.mm.__enter__.return_value하여 이 하면 에 할 수 open()의 우우회 our our our our our에 한다.do_something_with_data★★★★★★ 。

했습니다.open() 나의 ★★★★★★★★★★★★★★★.do_something_with_data이랬어요.

def do_something_with_data(*args, **kwargs):
    return args[0].split("\n")

그러면 문자열이 목록으로 변환되므로 일반 파일에서처럼 다음 작업을 수행할 수 있습니다.

for line in file:
    #do action

경기에 조금 늦을 수도 있지만, 전화할 때 이게 효과가 있었어요.open새로운 파일을 작성할 필요 없이 다른 모듈로 이동합니다.

test.py

import unittest
from mock import Mock, patch, mock_open
from MyObj import MyObj

class TestObj(unittest.TestCase):
    open_ = mock_open()
    with patch.object(__builtin__, "open", open_):
        ref = MyObj()
        ref.save("myfile.txt")
    assert open_.call_args_list == [call("myfile.txt", "wb")]

MyObj.py

class MyObj(object):
    def save(self, filename):
        with open(filename, "wb") as f:
            f.write("sample text")

「」에 하면,open__builtin__내 모듈로, 내 모듈로, 내 모듈로.mock_open()파일 작성 없이 파일에 대한 모의 쓰기를 할 수 있습니다.

주의: cython을 사용하는 모듈을 사용하는 경우 또는 프로그램이 cython에 의존하는 경우 다음을 포함하여 cython의 모듈을 Import해야 합니다.import __builtin__을 사용하다은 보편적인 것을 할 수 것입니다.__builtin__이치노

파일이 더 이상 필요하지 않은 경우 테스트 방법을 꾸밀 수 있습니다.

@patch('builtins.open', mock_open(read_data="data"))
def test_testme():
    result = testeme()
    assert result == "data"

내장된 open() 함수를 unittest로 패치하려면 다음 절차를 수행합니다.

이것은 패치가 json 설정을 읽기 위해 기능했습니다.

class ObjectUnderTest:
    def __init__(self, filename: str):
        with open(filename, 'r') as f:
            dict_content = json.load(f)

조롱 대상이 io입니다.open() 함수에 의해 반환된 TextIOWrapper 객체

@patch("<src.where.object.is.used>.open",
        return_value=io.TextIOWrapper(io.BufferedReader(io.BytesIO(b'{"test_key": "test_value"}'))))
    def test_object_function_under_test(self, mocker):

하고 pytest좋은 소식은 파이썬3의 경우,unittest수입하다

제 접근 방식은 이렇습니다.'I'를 .conftest.py"Pytest" "Pytest" "Pytest" :

from unittest.mock import MagicMock, mock_open

import pytest
from pytest_mock import MockerFixture


class FileMock(MagicMock):

    def __init__(self, mocker: MagicMock):
        super().__init__()

        self.__dict__ = mocker.__dict__

    @property
    def read_data(self):
        return self.side_effect

    @read_data.setter
    def read_data(self, mock_data: str):
        """set mock data to be returned when `open(...).read()` is called."""
        self.side_effect = mock_open(read_data=mock_data)


@pytest.fixture
def mock_file_open(mocker: MockerFixture) -> FileMock:
    return FileMock(mocker.patch('builtins.open'))

가 한 곳은 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★.read_data좀좀더버버하틱하게기해성성성성성요요 。에서는 어떤 할 수 .open()돌아와야 해

에는 '아까'와 같은 있다.test_it_works.py의도한 기능을 확인하기 위한 테스트 케이스는 다음과 같습니다.

def test_mock_file_open_works(mock_file_open):
    mock_file_open.read_data = 'hello\nworld!'

    with open('/my/file/here', 'r') as in_file:
        assert in_file.readlines() == ['hello\n', 'world!']

    mock_file_open.assert_called_with('/my/file/here', 'r')

여기 요점을 확인해 보세요.

python의 읽기 및 쓰기 기능을 패치하기 위해 github 스니펫에서 발신됩니다.

소스 링크는 이쪽입니다.

import configparser
import pytest

simpleconfig = """[section]\nkey = value\n\n"""

def test_monkeypatch_open_read(mockopen):
    filename = 'somefile.txt'
    mockopen.write(filename, simpleconfig)
 
    parser = configparser.ConfigParser()
    parser.read(filename)
    assert parser.sections() == ['section']
 
def test_monkeypatch_open_write(mockopen):
    parser = configparser.ConfigParser()
    parser.add_section('section')
    parser.set('section', 'key', 'value')
 
    filename = 'somefile.txt'
    parser.write(open(filename, 'wb'))
    assert mockopen.read(filename) == simpleconfig

단순 @patch with assert

@patch를 사용하고 싶은 경우.open()은 핸들러 내부에서 호출되어 읽힙니다.

    @patch("builtins.open", new_callable=mock_open, read_data="data")
    def test_lambda_handler(self, mock_open_file):
        
        lambda_handler(event, {})

언급URL : https://stackoverflow.com/questions/1289894/how-do-i-mock-an-open-used-in-a-with-statement-using-the-mock-framework-in-pyth

반응형