Flask单元测试:无法模拟发布请求中的函数



我有以下烧瓶应用程序。

# 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服务器。

最新更新