Yev*_*evs 7 testing unit-testing python-3.x
我是新手测试,需要一些帮助.
假设有这种方法:
from urllib.request import urlopen
def get_posts():
with urlopen('some url here') as data:
return json.loads(data.read().decode('utf-8'))
Run Code Online (Sandbox Code Playgroud)
问题是如何测试这个方法(如果可能的话,使用mock.patch装饰器)?
我现在拥有的:
@mock.patch('mymodule.urlopen')
def test_get_post(self, mocked_urlopen):
mocked_urlopen.__enter__ = Mock(return_value=self.test_data)
mocked_urlopen.__exit__ = Mock(return_value=False)
...
Run Code Online (Sandbox Code Playgroud)
但它似乎没有奏效.
PS有没有方便的方法在测试中使用数据变量(哪种类型是HTTPResponse),所以它可能只是简单的字符串?
小智 8
我也在与此作斗争,最后弄清楚了。(Python 3语法):
import urllib.request
import unittest
from unittest.mock import patch, MagicMock
class TestUrlopen(unittest.TestCase):
@patch('urllib.request.urlopen')
def test_cm(self, mock_urlopen):
cm = MagicMock()
cm.getcode.return_value = 200
cm.read.return_value = 'contents'
cm.__enter__.return_value = cm
mock_urlopen.return_value = cm
with urllib.request.urlopen('http://foo') as response:
self.assertEqual(response.getcode(), 200)
self.assertEqual(response.read(), 'contents')
@patch('urllib.request.urlopen')
def test_no_cm(self, mock_urlopen):
cm = MagicMock()
cm.getcode.return_value = 200
cm.read.return_value = 'contents'
mock_urlopen.return_value = cm
response = urllib.request.urlopen('http://foo')
self.assertEqual(response.getcode(), 200)
self.assertEqual(response.read(), 'contents')
response.close()
Run Code Online (Sandbox Code Playgroud)
Yev*_*evs -1
好的,所以我编写了简单的类来模拟上下文管理器。
class PatchContextManager:
def __init__(self, method, enter_return, exit_return=False):
self._patched = patch(method)
self._enter_return = enter_return
self._exit_return = exit_return
def __enter__(self):
res = self._patched.__enter__()
res.context = MagicMock()
res.context.__enter__.return_value = self._enter_return
res.context.__exit__.return_value = self._exit_return
res.return_value = res.context
return res
def __exit__(self, type, value, tb):
return self._patched.__exit__()
Run Code Online (Sandbox Code Playgroud)
用法:
with PatchContextManager('mymodule.method', 'return_string') as mocked:
a = mymodule.method(47) # a == 'return_string'
mocked.assert_called_with(47)
...
Run Code Online (Sandbox Code Playgroud)