[英]Flask unit-test: Unable to mock a function in a post request
I have the following flask app.我有以下烧瓶应用程序。
# 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()
I wrote a unit-test for it using pytest
and tried to mock the query_sku
function using unittest.mock
.我使用
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']
But I was unable to mock that function within the request.但是我无法在请求中模拟该功能。 It just gave the following assertion error.
它只是给出了以下断言错误。
> assert response == {"sku": "dummy"}
E AssertionError: assert None == {'sku': 'dummy'}
E +None
E -{'sku': 'dummy'}
tests/unit_tests/test_api.py:34: AssertionError
How can I get it to work?我怎样才能让它工作?
[EDIT] [编辑]
I added in the query_sku
function below.我在下面的
query_sku
函数中添加了。 Intentionally return a value that is different from the Mock function return_value.有意返回一个与 Mock 函数 return_value 不同的值。
# predict.py
def query_sku(input_sku_list, topn):
return "actual function"
But the unit-test is still querying from the actual function, as shown below.但是单元测试仍然是从实际功能中查询,如下所示。
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']
Could you try this code ?你能试试这个代码吗?
Actually, the answer above did not work for me.实际上,上面的答案对我不起作用。 Rather than using MagicMock, I used @mock.patch and that worked.
我没有使用 MagicMock,而是使用了 @mock.patch 并且效果很好。 And it is less complicated too.
而且它也不那么复杂。 For example, in your app.py, you can have an API endpoint that you want to stub out with a mock:
例如,在你的 app.py 中,你可以有一个 API 端点,你想用一个 mock 来存根:
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
Now in test_app.py, you can stub it out like this:现在在 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()
The important thing is the definition of mock.patch('app.fetch_nodes') which references the fetch_nodes function in app.py and secondly it is passed to the test function as "mocked".重要的是 mock.patch('app.fetch_nodes') 的定义,它引用 app.py 中的 fetch_nodes 函数,其次它作为“模拟”传递给测试函数。 Then we set the return value of "mocked".
然后我们设置“mocked”的返回值。 And finally call the flask endpoint.
最后调用烧瓶端点。 Now the flask endpoint will use the mock instead of actually hitting an sftp server.
现在烧瓶端点将使用模拟而不是实际访问 sftp 服务器。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.