我需要进行单元测试是否调用由Flask route()
修饰的方法。
如果可能的话,我想在没有修改测试的原始代码的情况下执行此操作,因此模拟该方法将完美地满足我的要求。
因此我问这个具体的问题,关于如何模拟一个装饰的请求方法(我想强调这一点,试图避免人们用不太具体的答案浪费时间)......
示例应用jflask.py
:
from flask import Flask
app = Flask(__name__)
app.config.from_object(__name__)
@app.route('/hello') # This method represents the code under test.
def hello(): # I want to assert that this method gets
return 'Hello, World' # called without modifying this code.
if __name__ == "__main__":
app.run()
在单元测试中,我使用@patch()
来模拟方法,所以我可以断言它被调用,但断言失败了。即当我期望它时,模拟方法不被调用。
样本单元测试test_hello.py
:
import unittest
import jflask
from unittest.mock import patch
class jTest(unittest.TestCase):
def setUp(self):
#jflask.app.testing = True
self.app = jflask.app.test_client()
@patch('jflask.hello') # mock the hello() method
def test_hello(self, mock_method):
rv = self.app.get('/hello')
mock_method.assert_called() # this assertion fails
我做错了什么?
背景
有关我正在尝试测试的实际行为的一些背景信息 (因为上面只是一个浓缩的测试用例,并且可能看起来并不完全合理)。
在实际代码中我是单元测试,有一个before_request()
处理程序
为应用程序安装。在处理每个请求之前,Flask会调用它
在某些情况下,此处理程序已设计为返回响应值
导致Flask请求处理停止(在此应用程序的情况下,此功能用于集中验证请求参数),以便通常的路由请求处理程序(故意)不会被调用。
我的单元测试需要声明请求处理已停止 或继续,视情况而定。 因此,我的测试需要模拟真实的请求处理程序并断言是否 是否被召唤。
答案 0 :(得分:0)
这有点hacky但你可以注射一个记录器。
@app.route(...):
def hello(logger=None):
logger = logger or self.logger
logger.info(...)
return ...
def test_...(self):
logger = MagicMock()
self.app.get(logger)
self.assertTrue(logger.info.called)
答案 1 :(得分:0)
from functools import wraps
import logging
from datetime import datetime
logging.basicConfig(filename=datetime.now().strftime('%d_%m_%Y.log'),level=logging.INFO)
def logger_required(f):
@wraps(f)
def decorated(*args, **kwargs):
logging.info(f.__name__ + ' was called')
return f(*args, **kwargs)
return decorated
@app.route('/hello')
@logger_required
def hello(): # I want to assert that this gets called
return 'Hello, World'