首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法在Flask测试用例会话中检索数据库对象

无法在Flask测试用例会话中检索数据库对象
EN

Stack Overflow用户
提问于 2018-06-25 11:59:23
回答 2查看 994关注 0票数 2

我正在测试一个使用flask-restfulsqlalchemyflask-sqlalchemyfactory-boy创建的应用程序接口。

我遇到了一个奇怪的问题,在使用factoryGET请求之前创建的对象是可用的,但是在post/put调用之前创建的对象是不可用的。

我已经建立了一个基于flask-testing的测试用例类

代码语言:javascript
复制
# tests/common.py
from flask_testing import TestCase as FlaskTestCase

from app import create_app
from database import db
from config import TestConfig


class TestCase(FlaskTestCase):
    def create_app(self):
        return create_app(TestConfig)

    def setUp(self):
    db.create_all()

    def tearDown(self):
        db.session.remove()
        db.drop_all()

测试工厂:

代码语言:javascript
复制
# tests/factory.py

import factory

from database import db

from ..models import Item

class ItemFactory(factory.alchemy.SQLAlchemyModelFactory):
    class Meta:
        model = Item
        sqlalchemy_session = db.session

资源:

代码语言:javascript
复制
# resources.py
from flask import request
from flask_restful import Resource

from database import db
from .models import Item
from .serializers import ItemSerializer

class ItemResource(Resource):
    def get(self, symbol):
        obj = db.session(Item).filter(Item.symbol == symbol).first_or_404()
    return ItemSerializer(obj).data

    def put(self, symbol):
        params = request.get_json(silent=True)
        query = db.session(Item).filter(Item.symbol == symbol).update(params)

        db.session.commit()

        obj = db.session(Item).filter(Item.symbol == symbol).first_or_404()
        return ItemSerializer(obj).data

测试:

代码语言:javascript
复制
# tests/test_resources.py
import json

from tests.common import TestCase
from tests.factory import ItemFactory


def parse_response(response):
    return json.loads(response.get_data().decode())


class ResourcesTest(TestCase):
    def test_get_item(self):
        symbol = 'TEST'
        ItemFactory(symbol=symbol)

        response = self.client.get('/api/v1/items/%s' % symbol)
        results = parse_response(response)

        self.assertEqual(response.status_code, 200)
        self.assertEqual(results['symbol'], symbol)

    def test_update_item(self):
        symbol = 'TEST'
        new_symbol = 'TEST_NEW'
        ItemFactory(symbol=symbol)

        response = self.client.put('/api/v1/items/%s' % symbol, json={'symbol': new_symbol})
        results = parse_response(response)

        self.assertEqual(response.status_code, 200)

test_update_item中,我收到的是404。在我们进入self.client.put之前,检查数据库显示创建了新的Item。但是,当我们到达资源中的put方法时,db.session(Item).query.all()返回一个空数组。

flask-testing文档中,我发现了这一段:

Another gotcha is that Flask-SQLAlchemy also removes the session instance at the end of every request (as should any thread safe application using SQLAlchemy with scoped_session). Therefore the session is cleared along with any objects added to it every time you call client.get() or another client method.

我认为问题出在对待会话的方式上,但是还没能拿出任何解决方案来确保我的测试通过。另一个有趣的观察是,对于self.client.putself.client.post,如果我更改发布为self.client.put('/some/url', data={'symbol': symbol})的数据,这些对象将在会话中可用。

EN

回答 2

Stack Overflow用户

发布于 2018-06-25 12:19:54

好了,我找到了一个复杂的方法来解决这个问题。我认为调用request.get_json会在其他地方实例化会话。解决方案是覆盖json数据发布的方式。

tests/common.py

代码语言:javascript
复制
import json

from flask_testing import TestCase as FlaskTestCase
from flask.testing import FlaskClient

from app import create_app
from database import db
from config import TestConfig


class TestClient(FlaskClient):
    def open(self, *args, **kwargs):
        if 'json' in kwargs:
            kwargs['data'] = json.dumps(kwargs.pop('json'))
            kwargs['content_type'] = 'application/json'
        return super(TestClient, self).open(*args, **kwargs)


class TestCase(FlaskTestCase):
    def create_app(self):
        app = create_app(TestConfig)
        app.test_client_class = TestClient
        return app

    def setUp(self):
        db.create_all()

    def tearDown(self):
        db.session.remove()
        db.drop_all()

因此,基本上我们将测试客户端post/put调用中的任何json kwarg转换为数据,并将content_type设置为json。在这里偶然发现了这个(https://stackoverflow.com/a/40688088)。

票数 1
EN

Stack Overflow用户

发布于 2018-06-26 18:18:08

您可能需要了解一下SQLAlchemy会话处理。

factory_boy文档描述了几个选项:https://factoryboy.readthedocs.io/en/latest/orms.html#managing-sessions

看起来工厂在SQLAlchemy会话中创建了对象,但该会话并未写入数据库。当您的代码进入flask端时,该上下文可能正在使用另一个到数据库的连接(请参阅您引用的flask-testing文档),因此看不到尚未提交的对象。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51016103

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档