我可以在测试 Flask 应用程序功能时使用模拟吗?

kjo*_*sen 4 unit-testing mocking flask python-3.x

我正在尝试在我的 Flask 应用程序上测试一些调用外部 API 的路由,我想模拟这些路由。

路由设置如下:

@app.route('/url/<string::arg>')
def route_function(arg):
    data = external_api(arg)
    response = make_response(data)
    # configure response
    return response
Run Code Online (Sandbox Code Playgroud)

我最初尝试过这样的事情:

class TestFlaskApp(unittest.TestCase):
    def setUp(self):
        self.app = app.test_client()

    @patch('external_api',
           side_effect=mock_api)
    def test_flask_route(self, api):
        result = app.get('/url/arg')
        self.assertEqual(result.status_code, 200)
        api.assert_called_once_with('arg')
Run Code Online (Sandbox Code Playgroud)

...失败了。没有调用模拟 API 函数,因为我认为模拟不适用于应用程序上下文。

我也试过这个,认为我可以直接测试路由功能,从而避免使用应用程序上下文:

class TestAppFunctions(unittest.TestCase):
    @patch('external_api',
           side_effect=mock_api)
    def test_flask_function(self, api):
        result = my_flask_app.route_function('arg')
        self.assertEqual(result.status_code, 200)
        api.assert_called_once_with('arg')
Run Code Online (Sandbox Code Playgroud)

...但这也不起作用,因为要做出响应,route_function需要应用程序上下文。

那么有没有办法在应用程序上下文中进行模拟?我还能如何在不触发外部 API 调用的情况下测试这些路由?

kjo*_*sen 5

Oluwafemi Sule是对的……我只需要在函数使用的地方打补丁,而不是在定义的地方打补丁。

您需要将对象路径传递给 patch 函数,以便它可以在运行时解析并替换为模拟。例如,如果external_api function在名为 的模块中调用,该模块routes又包含在名为 的包中my_shining_app,补丁将作为my_shining_app.routes.external_api

请注意,路径应该是函数被调用的地方(即它被替换为模拟的地方)而不是它被定义的地方

  • 举一个清楚的例子,因为我必须读两遍才能得到正确的结果:假设你已经从“main.py”中的“mymodule.py”导入了“myfunc”。您必须使用 utnittest 修补 `main.myfunc` 才能使其工作。不是“mymodule.myfunc”。 (2认同)