我正在测试特定的响应代码,并希望在代码不同的情况下(例如未经授权的401
)模拟一个测试用例。我正在使用Python 3.7 http.client库和pytest
到目前为止,我尝试使用@patch
装饰器并使用side_effect
调用函数以触发异常
我的测试用例:
from unittest import mock
from application import shorten_url
def mock_status(url):
raise ConnectionError
@patch("application.shorten_url", side_effect=mock_status)
def test_bitly(client):
with pytest.raises(ConnectionError) as e:
shorten_url("something")
我的代码:
def shorten_url(url):
conn = http.client.HTTPSConnection("api-ssl.bitly.com", timeout=2)
headers = {
"Content-Type": "application/json",
"Authorization": "Bearer abcd",
}
payload = json.dumps({"long_url": url})
conn.request("POST", "/v4/shorten", payload, headers)
res = conn.getresponse()
if not res.status == 201:
raise ConnectionError
data = json.loads(res.read())
return data["link"]
我不太了解如何使用mock
和side_effect
正确引发此异常。
答案 0 :(得分:0)
一个朋友帮我解决了这个问题,这似乎行得通(对我来说仍然很混乱):
from unittest.mock import patch, MagicMock
@patch("http.client.HTTPSConnection")
@patch("http.client.HTTPResponse")
def test_bitly(mock_conn, mock_res):
mock_res.status = 400
mock_conn.getresponse = MagicMock(return_value=mock_res)
with pytest.raises(ConnectionError):
shorten_url("fake-url")
答案 1 :(得分:0)
我认为这个答案更容易理解。首先,我创建了一个假的 http 连接和响应:
class FakeHTTPConnection:
def __init__(self, status):
self.status = status
def request(self, *args):
# If you need to do any logic to change what is returned, you can do it in this class
pass
def getresponse(self):
return FakeHTTPResponse(self.status)
class FakeHTTPResponse:
def __init__(self, status):
self.status = status
然后在我的测试类中,我改写了 http.client.HTTPConnection
来创建我的实例。
class TestFoo(unittest.TestCase):
@patch('http.client.HTTPConnection', new=MagicMock(return_value=FakeHTTPConnection(200)))
def test_foo_success(self):
conn = http.client.HTTPConnection("127.0.0.1")
conn.request("GET", "/endpoint")
response = conn.getresponse()
success = response.status == http.HTTPStatus.OK