如何在flask-restful中对Resource类内部的函数进行单元测试?

add*_*ted 6 python flask flask-restful

我对单元测试相当陌生,对 RESTful API 开发也比较陌生。我想知道如何对 Flask Restful 中的 Resource 类内的函数进行单元测试?我可以对端点的响应进行单元测试,但我不知道如何对端点控制器类内的各个函数进行测试。

下面是我的应用程序代码。它有3个文件,包括测试:

  • api.py
  • 控制器_foo.py
  • test_controller_foo.py
# api.py

from flask import Flask
from flask_restful import Api

from .controller_foo import ControllerFoo


def create_app(config=None):
    app = Flask(__name__)
    app.config['ENV'] ='development'
    return app

application = app = create_app()
api = Api(app)

api.add_resource(ControllerFoo, '/ctrl')

if __name__ == "__main__":
    app.run(debug=True)
Run Code Online (Sandbox Code Playgroud)
# controller_foo.py

from flask_restful import Resource
from flask import request

class ControllerFoo(Resource):
    """
    basically flask-restful's Resource method is a wrapper for flask's MethodView
    """
    def post(self):
        request_data = self.handle_request()
        response = self.process_request(request_data)
        return response

    def handle_request(self):
        json = request.get_json()
        return json

    def process_request(self, data):
         # do some stuffs here
         return {'foo': 'bar'}
Run Code Online (Sandbox Code Playgroud)

我在用unittest

# test_controller_foo.py

import unittest

from api import app
from .controller_foo import ControllerFoo

# initiating class to try testing but I don't know how to start
ctrl = ControllerFoo()

class ControllerFooTestCase(unittest.TestCase):
    def setUp(self):
        self.app = app
        self.app.config['TESTING'] = True
        self.client = app.test_client()
        self.payload = {'its': 'empty'}

    def tearDown(self):
        pass

    def test_get_response(self):
        response = self.client.post('/ctrl', json=self.payload)
        expected_resp = {
            'foo': 'bar'
        }
        self.assertEqual(response.status_code, 200)
        self.assertDictEqual(response.get_json(), expected_resp)

if __name__ == "__main__":
    unittest.main()
Run Code Online (Sandbox Code Playgroud)

我想知道如何正确进行单元测试handle_requestprocess_request功能

编辑:修复我的错误代码。感谢Laurent LAPORTE的精彩报道。

Lau*_*RTE 5

您的代码中有几个错误,因此这不容易解释。

\n\n

首先,使用 Flask(和 Flask-Restful)进行测试的推荐方法是使用PyTest而不是unittest,因为它更容易设置和使用。

\n\n

查看文档:测试 Flask 应用程序

\n\n

但是,您可以从 unittest\xe2\x80\xa6 开始

\n\n

注意:app您可能会对您的模块和该模块中的实例感到困惑app。因此,为了避免这种情况,我导入了该模块。另一个好的做法是根据测试模块命名您的测试模块:“app.py”=>“test_app.py”。您也可能对controller模块和controller。最佳实践是使用更精确的名称,例如“controller_foo”或其他名称\xe2\x80\xa6

\n\n

这是一个工作单元测试:

\n\n
# test_app.py\n\nimport unittest\n\nimport app\n\n\nclass ControllerTestCase(unittest.TestCase):\n    def setUp(self):\n        self.app = app.app\n        self.app.config[\'TESTING\'] = True\n        self.client = self.app.test_client()\n        self.payload = {\'its\': \'empty\'}\n\n    def test_get_response(self):\n        response = self.client.post(\'/ctrl\', json=self.payload)\n        expected_resp = {\'foo\': \'bar\'}\n        self.assertEqual(response.status_code, 200)\n        self.assertDictEqual(response.get_json(), expected_resp)\n\n\nif __name__ == "__main__":\n    unittest.main()\n
Run Code Online (Sandbox Code Playgroud)\n\n

正如你所看到的,我还修复了发布的 URL,在你的应用程序中,URL 是“/ctrl”,而不是“controller”。

\n\n

此时,测试可以运行,但又出现另一个错误:

\n\n
Ran 1 test in 0.006s\n\nFAILED (errors=1)\n\nError\nTraceback (most recent call last):\n  ...\nTypeError: process_request() takes 1 positional argument but 2 were given\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果您查看您的process_request()方法,您会发现您错过了该self参数。像这样改变它。

\n\n
    def process_request(self, data):\n        # do some stuffs here\n        return {\'foo\': \'bar\'}\n
Run Code Online (Sandbox Code Playgroud)\n\n

你的测试应该通过。

\n\n

但是,这不是实现 Flask-Restful 控制器的正确方法。阅读文档并使用getpost方法\xe2\x80\xa6

\n