我有以下烧瓶应用程序。
# app.py
from flask import Flask, request
from predict import query_sku
app = Flask(__name__)
@app.route("/predict", methods=["POST"])
def predict():
content = request.json
max_results = content["resultSize"]
input_sku_list = content["sku"]
skus = query_sku(input_sku_list, max_results)
return {"sku": skus}
if __name__ == "__main__":
app.run()
我使用pytest
为它编写了一个单元测试,并尝试使用unittest.mock
模拟query_sku
函数。
import sys
from unittest.mock import Mock
import pytest
import app
def test_api_mocked_model():
sys.modules["predict"] = Mock()
from predict import query_sku
query_sku.return_value = "dummy"
with app.app.test_client() as client:
response = client.post('/predict', json={"resultSize":10,"sku": "x"}).json
assert response == {"sku": "dummy"}
del sys.modules['predict']
但我无法在请求中模拟该功能。它只是给出了以下断言错误。
> assert response == {"sku": "dummy"}
E AssertionError: assert None == {'sku': 'dummy'}
E +None
E -{'sku': 'dummy'}
tests/unit_tests/test_api.py:34: AssertionError
我怎样才能让它工作?
[EDIT]
我在下面的query_sku
函数中添加了。有意返回一个不同于Mock函数return_value的值。
# predict.py
def query_sku(input_sku_list, topn):
return "actual function"
但是单元测试仍然在从实际函数中进行查询,如下所示。
assert response == {"sku": "dummy"}
E AssertionError: assert {'sku': 'actual function'} == {'sku': 'dummy'}
E Differing items:
E {'sku': 'actual function'} != {'sku': 'dummy'}
from unittest.mock import MagicMock
def test_api_mocked_model():
## sys.modules["predict"] = Mock() ## why sys module ?
from predict import query_sku
query_sku = MagicMock(return_value="dummy") # mock directly
with app.app.test_client() as client:
response = client.post('/predict', json={"resultSize":10,"sku": "x"}).json
assert response == {"sku": "dummy"}
del sys.modules['predict']
你能试试这个代码吗?
实际上,上面的答案对我不起作用。我没有使用MagicMock,而是使用@mock.patch,这就起了作用。它也不那么复杂。例如,在你的app.py中,你可以有一个API端点,你想用一个mock:截取它
app.py
def fetch_nodes(usr, passwd, hostname, node_name):
sftp_connection = get_sftp_connection(usr, passwd, hostname)
nodes = sftp_connection.listdir_attr(node_name)
return nodes
现在在test_app.py中,您可以像这样截取它:
test_app.py
from app import app
import unittest
from unittest import mock
class FlaskTest(unittest.TestCase):
@mock.patch('app.fetch_nodes')
def test_list_child_nodes(self, mocked):
tester = app.test_client(self)
mocked.return_value = []
response = tester.post("/api/listchildnodes", json={
'usr': 'test',
'jwt': 'test',
'node_name': 'test',
})
statuscode = response.status_code
self.assertEqual(statuscode, 200)
if __name__ == "__main__":
unittest.main()
重要的是mock.patch("app.fetch_nodes"(的定义,它引用app.py中的fetch_nodes函数;嘲笑";。然后我们设置返回值"0";嘲笑";。最后调用烧瓶端点。现在flask端点将使用mock,而不是实际访问sftp服务器。