with 문 (파이썬의 모의 프레임 워크 사용)에 사용 된 오픈을 어떻게 조롱합니까?

StackOverflow https://stackoverflow.com/questions/1289894

  •  18-09-2019
  •  | 
  •  

문제

모의로 다음 코드를 테스트하는 방법 (모의, 패치 데코레이터 및 센티넬 사용 Michael Foord의 모의 프레임 워크):

def testme(filepath):
    with open(filepath, 'r') as f:
        return f.read()
도움이 되었습니까?

해결책

이 작업을 수행하는 방법은 Mock 0.7.0에서 변경되었으며, 특히 MagicMock을 사용하여 Python Protocol Methods (Magic Methods)를 조롱하는 것을 지원합니다.

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_open 의 일부입니다 mock 프레임 워크이며 사용하기가 매우 간단합니다. patch 컨텍스트로 사용되는 패치 된 객체를 대체하는 데 사용되는 객체를 반환합니다. 테스트를 더 간단하게 만드는 데 사용할 수 있습니다.

파이썬 3.x

사용 builtins 대신에 __builtin__.

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")

파이썬 2.7

mock 의 일부가 아닙니다 unittest 그리고 당신은 패치해야합니다 __builtin__

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")

데코레이터 케이스

당신이 사용한다면 patch 데코레이터를 사용합니다 mock_open()결과 new patch의 주장은 조금 이상 할 수 있습니다.

이 경우 사용하는 것이 좋습니다 new_callable patch의 주장과 모든 추가 주장이 patch 사용하지 않으면 전달됩니다 new_callable 설명 된대로 기능 patch 선적 서류 비치.

Patch ()는 임의의 키워드 인수를 취합니다. 이들은 건설시 모의 (또는 New_Callable)로 전달됩니다.

예를 들어 장식 된 버전입니다 파이썬 3.x 이다:

@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 테스트 기능의 인수로 모의 개체를 추가합니다.

최신 버전의 Mock을 사용하면 정말 유용한 것을 사용할 수 있습니다. mock_open 돕는 사람:

mock_open (mock = none, read_data = 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을 사용합니다

게임에 조금 늦었을 수도 있지만 전화 할 때 저에게 효과가있었습니다. 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에 의존하는 경우 어떤 식 으로든 가져와야합니다. 시톤 __builtin__ 기준 치수 포함하여 import __builtin__ 파일 상단에. 당신은 보편적 인 것을 조롱 할 수 없습니다 __builtin__ Cython을 사용하는 경우.

상단 답변은 유용하지만 조금 확장했습니다.

파일 객체의 값을 설정하려면 ( f 안에 as 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 우리가 원하는 모의 데이터/파일 개체를 반환하기 위해 (따라서 mm.__enter__.return_value). 위의 방식으로 2 개의 모의 로이 작업을 수행하면 전달 된 인수를 포착 할 수 있습니다. open() 그리고 그들을 우리에게 전달하십시오 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
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top