SQLAlchemy:为具有循环关系的模型类编写单元测试[重复]

问题描述 投票:1回答:1

我正在尝试编写下一个UserModel类的单元测试代码:

from db import db

from logs import Logger


class UserModel(db.Model):
    __tablename__ = 'users'

    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(30))
    password = db.Column(db.String(30))
    recipes = db.relationship(
        'RecipeModel',
        backref='author',
        lazy='dynamic'
    )

    def __init__(self, email, password):
        self.email = email
        self.password = password

    def save(self):
        logger = Logger('save::usermodel::models::flask')
        logger.debug('Starting save user in database')
        db.session.add(self)
        db.session.commit()

    @classmethod
    def find_by_email(cls, email):
        logger = Logger('findbyemail::usermodel::models::flask')
        logger.debug('Searchin user by email')
        return cls.query.filter_by(email=email).first()

    @classmethod
    def find_by_id(cls, user_id):
        logger = Logger('findbyid::usermodel::models::flask')
        logger.debug('Searching user by id')
        return cls.query.filter_by(id=user_id).first()

    def delete_user(self):
        logger = Logger('deleteuser::usermodel::models::flask')
        logger.debug('Deleting item')
        db.session.delete(self)
        db.session.commit()

    def __repr__(self):
        return f'User: {self.email}'

如您所见;用户与配方之间存在“一对多”的关系。另一方面;食谱本身具有“多对多”的关系:

from db import db

from logs import Logger

recipes_relationship = db.Table(
    'RecipeChild',
    db.Column('recipe_relation_id', db.Integer, primary_key=True),
    db.Column('parent_recipe_id', db.Integer, db.ForeignKey('recipes.id')),
    db.Column('child_recipe_id', db.Integer, db.ForeignKey('recipes.id'))
)


class RecipeModel(db.Model):
    __tablename__ = 'recipes'

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(30))
    instructions = db.Column(db.String(300))
    photo = db.Column(db.BLOB)

    parent_recipe = db.relationship(
        'recipes',
        secondary=recipes_relationship,
        primaryjoin=id == recipes_relationship.c.child_recipe_id,
        secondaryjoin=id == recipes_relationship.c.parent_recipe_id,
        backref='child_recipe'
    )

    ingredients = db.relationship(
        'IngredientsRecipesModel',
        backref='recipe',
        lazy='dynamic'
    )
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'))

    def __init__(self, recipe_entity):
        self.name = recipe_entity.name
        self.instructions = recipe_entity.instructions
        self.user_id = recipe_entity.user_id
        self.photo = recipe_entity.photo

    @classmethod
    def find_by_name(cls, name):
        logger = Logger('findbyname::recipemodel::models::flask')
        logger.debug('Searchin recipe by name')
        return cls.query.filter_by(name=name).first()

    def save(self):
        logger = Logger('save::recipemodel::models::flask')
        logger.debug('Recipe saved in database')
        db.session.add(self)
        db.session.commit()

    def delete(self):
        logger = Logger('delete::usermodel::models::flask')
        logger.debug('Recipe deleted from database')
        db.session.delete(self)
        db.session.commit()

至此,一切正常,它应该可以正常工作。当我尝试为UserModel类编写测试代码时,就会出现问题。运行测试时,出现下一个错误:

======================================================================
ERROR: test_user_creation (models.test_user_model.TestUserModel)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/adrian.ferrereses/projects/c-c/back-c-c/models/test_user_model.py", line 21, in setUp
    self.session.add(UserModel(self.email, self.password))
  File "<string>", line 2, in __init__
  File "/Users/adrian.ferrereses/projects/c-c/back-c-c/venv/lib/python3.7/site-packages/sqlalchemy/orm/instrumentation.py", line 376, in _new_state_if_none
    state = self._state_constructor(instance, self)
  File "/Users/adrian.ferrereses/projects/c-c/back-c-c/venv/lib/python3.7/site-packages/sqlalchemy/util/langhelpers.py", line 855, in __get__
    obj.__dict__[self.__name__] = result = self.fget(obj)
  File "/Users/adrian.ferrereses/projects/c-c/back-c-c/venv/lib/python3.7/site-packages/sqlalchemy/orm/instrumentation.py", line 202, in _state_constructor
    self.dispatch.first_init(self, self.class_)
  File "/Users/adrian.ferrereses/projects/c-c/back-c-c/venv/lib/python3.7/site-packages/sqlalchemy/event/attr.py", line 322, in __call__
    fn(*args, **kw)
  File "/Users/adrian.ferrereses/projects/c-c/back-c-c/venv/lib/python3.7/site-packages/sqlalchemy/orm/mapper.py", line 3360, in _event_on_first_init
    configure_mappers()
  File "/Users/adrian.ferrereses/projects/c-c/back-c-c/venv/lib/python3.7/site-packages/sqlalchemy/orm/mapper.py", line 3248, in configure_mappers
    mapper._post_configure_properties()
  File "/Users/adrian.ferrereses/projects/c-c/back-c-c/venv/lib/python3.7/site-packages/sqlalchemy/orm/mapper.py", line 1947, in _post_configure_properties
    prop.init()
  File "/Users/adrian.ferrereses/projects/c-c/back-c-c/venv/lib/python3.7/site-packages/sqlalchemy/orm/interfaces.py", line 196, in init
    self.do_init()
  File "/Users/adrian.ferrereses/projects/c-c/back-c-c/venv/lib/python3.7/site-packages/sqlalchemy/orm/relationships.py", line 1913, in do_init
    self._process_dependent_arguments()
  File "/Users/adrian.ferrereses/projects/c-c/back-c-c/venv/lib/python3.7/site-packages/sqlalchemy/orm/relationships.py", line 1975, in _process_dependent_arguments
    self.target = self.entity.persist_selectable
  File "/Users/adrian.ferrereses/projects/c-c/back-c-c/venv/lib/python3.7/site-packages/sqlalchemy/util/langhelpers.py", line 855, in __get__
    obj.__dict__[self.__name__] = result = self.fget(obj)
  File "/Users/adrian.ferrereses/projects/c-c/back-c-c/venv/lib/python3.7/site-packages/sqlalchemy/orm/relationships.py", line 1898, in entity
    % (self.key, type(argument))
sqlalchemy.exc.ArgumentError: relationship 'parent_recipe' expects a class or a mapper argument (received: <class 'sqlalchemy.sql.schema.Table'>)

----------------------------------------------------------------------
Ran 1 test in 0.022s

FAILED (errors=1)

开始测试时,我没有做某件事,这使RecipeModel的关系失败。

这是我的测试代码:

import unittest

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

from models.user_model import UserModel
from models.recipe_model import RecipeModel
from db import db


class TestUserModel (unittest.TestCase):

    engine = create_engine('sqlite:///:memory:')
    Session = sessionmaker(bind=engine)
    session = Session()
    email = '[email protected]'
    password = '1234'

    def setUp(self):
        db.metadata.create_all(self.engine)
        self.session.add(UserModel(self.email, self.password))
        self.session.commit()

    def tearDown(self):
        db.metadata.drop_all(self.engine)

    def test_user_creation(self):
        result = self.session.query(UserModel).all()
        self.assertEqual(True, True)

如果要在此处验证整个项目为link

有什么想法吗?非常感谢您的宝贵时间

python flask sqlalchemy flask-sqlalchemy
1个回答
2
投票

更改

parent_recipe = db.relationship(
    'recipes',

with

parent_recipe = db.relationship(
    'RecipeModel',
© www.soinside.com 2019 - 2024. All rights reserved.