with 문에서 사용되는 open을 어떻게 조롱합니까 (Python에서 Mock 프레임 워크 사용)?
mocks를 사용하여 다음 코드를 테스트하는 방법 ( Michael Foord의 Mock 프레임 워크에서 제공하는 mock , 패치 데코레이터 및 센티넬 사용 ) :
def testme(filepath):
with open(filepath, 'r') as f:
return f.read()
이 방법은 mock 0.7.0에서 변경되었으며, 특히 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_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 ()는 임의의 키워드 인수를 사용합니다. 이것들은 구축시 Mock (또는 new_callable)에 전달됩니다.
예를 들어 Python 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 = 없음, read_data = 없음)
오픈 사용을 대체하기 위해 모의 객체를 만드는 헬퍼 함수. 직접 호출되거나 컨텍스트 관리자로 사용되는 열기에서 작동합니다.
mock 인수는 구성 할 mock 객체입니다. None (기본값)이면 MagicMock이 생성되며 API는 표준 파일 핸들에서 사용 가능한 메소드 또는 속성으로 제한됩니다.
read_data는 파일 핸들의 read 메소드가 리턴 할 문자열입니다. 기본적으로 빈 문자열입니다.
>>> 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()
Note as per docs for mock_open, this is specifically for read()
, so won't work with common patterns like for line in f
, for example.
Uses python 2.6.6 / mock 1.0.1
I might be a bit late to the game, but this worked for me when calling open
in another module without having to create a new file.
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")
By patching the open
function inside the __builtin__
module to my mock_open()
, I can mock writing to a file without creating one.
Note: If you are using a module that uses cython, or your program depends on cython in any way, you will need to import cython's __builtin__
module by including import __builtin__
at the top of your file. You will not be able to mock the universal __builtin__
if you are using cython.
The top answer is useful but I expanded on it a bit.
If you want to set the value of your file object (the f
in as f
) based on the arguments passed to open()
here's one way to do it:
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
Basically, open()
will return an object and with
will call __enter__()
on that object.
To mock properly, we must mock open()
to return a mock object. That mock object should then mock the __enter__()
call on it (MagicMock
will do this for us) to return the mock data/file object we want (hence mm.__enter__.return_value
). Doing this with 2 mocks the way above allows us to capture the arguments passed to open()
and pass them to our do_something_with_data
method.
I passed an entire mock file as a string to open()
and my do_something_with_data
looked like this:
def do_something_with_data(*args, **kwargs):
return args[0].split("\n")
This transforms the string into a list so you can do the following as you would with a normal file:
for line in file:
#do action
'Programming' 카테고리의 다른 글
“Thread.sleep”이없는“while (true)”가 Linux에서 100 % CPU 사용을 야기하지만 Windows에서는 왜 발생하지 않습니까? (0) | 2020.06.04 |
---|---|
웹 페이지가로드 될 때 포커스를 텍스트 상자로 자동 설정하는 방법은 무엇입니까? (0) | 2020.06.04 |
SQL Server에 대한 LIMIT 및 OFFSET에 해당합니까? (0) | 2020.06.04 |
Swift에서 NSDocumentDirectory를 찾는 방법은 무엇입니까? (0) | 2020.06.04 |
HSL에서 RGB 색상으로 변환 (0) | 2020.06.04 |