Python 在烧瓶单元测试中,如何模拟请求全局'g'对象上的对象?

Python 在烧瓶单元测试中,如何模拟请求全局'g'对象上的对象?,python,unit-testing,mocking,flask,werkzeug,Python,Unit Testing,Mocking,Flask,Werkzeug,我有一个flask应用程序,它正在\u filter之前的中设置数据库连接,非常类似于: 现在:我正在编写一些单元测试,我不希望它们进入数据库。我想用一个可以设置期望值的模拟对象替换g.db 我的测试使用的是app.test\u client(),如flask文档所示。示例测试类似于 def test(self): response = app.test_client().post('/endpoint', data={..}) self.assertEqual(response

我有一个flask应用程序,它正在\u filter之前的
中设置数据库连接,非常类似于:

现在:我正在编写一些单元测试,我不希望它们进入数据库。我想用一个可以设置期望值的模拟对象替换
g.db

我的测试使用的是
app.test\u client()
,如flask文档所示。示例测试类似于

def test(self):
    response = app.test_client().post('/endpoint', data={..})
    self.assertEqual(response.status_code, 200)
    ...
测试工作正常并通过,但它们正在影响数据库,正如我所说的,我想用模拟对象替换db访问。我在
test\u client
中找不到任何方法来访问
g
对象或更改before\u过滤器。

这是有效的

test\u app.py

from flask import Flask, g

app = Flask(__name__)

def connect_db():
    print 'I ended up inside the actual function'
    return object()

@app.before_request
def before_request():
    g.db = connect_db()


@app.route('/')
def root():
    return 'Hello, World'
from mock import patch
import unittest

from test_app import app


def not_a_db_hit():
    print 'I did not hit the db'

class FlaskTest(unittest.TestCase):

    @patch('test_app.connect_db')
    def test_root(self, mock_connect_db):
        mock_connect_db.side_effect = not_a_db_hit
        response = app.test_client().get('/')
        self.assertEqual(response.status_code, 200)

if __name__ == '__main__':
    unittest.main()
test.py

from flask import Flask, g

app = Flask(__name__)

def connect_db():
    print 'I ended up inside the actual function'
    return object()

@app.before_request
def before_request():
    g.db = connect_db()


@app.route('/')
def root():
    return 'Hello, World'
from mock import patch
import unittest

from test_app import app


def not_a_db_hit():
    print 'I did not hit the db'

class FlaskTest(unittest.TestCase):

    @patch('test_app.connect_db')
    def test_root(self, mock_connect_db):
        mock_connect_db.side_effect = not_a_db_hit
        response = app.test_client().get('/')
        self.assertEqual(response.status_code, 200)

if __name__ == '__main__':
    unittest.main()

因此,这将打印“我没有击中数据库”,而不是“我最终进入了实际函数”。显然,您需要根据您的实际用例调整模拟。

尝试此操作(我必须将其更改为'flask\u module.g.connect\u db')会出现
运行时错误:在请求上下文之外工作
我刚刚编写了一个更完整的示例,我已经实际测试并已运行。我喜欢这个想法!我唯一不明白的部分是
g=g()
,为什么这是必要的?我想你只是误解了这个例子。当我发布答案时,我想让他们实际运行。全局“g”对象不相关,因为它没有被修补。相反,正在修补的函数是
connect\u db
。在随机对接受的答案进行向下投票之前,您可能想玩一玩模拟和补丁库。回顾这一点,我看不出我是如何误解这一点的。不幸的是,我的投票现在被锁定了。很抱歉