【问题标题】:Pony ORM - tear down in testingPony ORM - 在测试中拆除
【发布时间】:2019-08-24 16:57:06
【问题描述】:

我正在使用 Pony ORM 来管理我正在开发的 python 包中的 sqlite 数据库。

我想使用 pytest 进行测试。

我的包提供了一个“代理”对象,用于连接到服务器 API 并检索“事件”。在初始化代理时,小马 orm 被设置并绑定到一个 sqlite db,无论是在内存中(用于测试)还是作为文件。

    def setup_db(filepath=None):
        if filepath:
            db.bind(provider="sqlite", filename=filepath, create_db=True)
        else:
            db.bind(provider="sqlite", filename=":memory:", create_db=True)
        db.provider.converter_classes.append((Enum, EnumConverter))
        db.generate_mapping(create_tables=True)

事件的状态使用 pony orm 存储在 sqlite db 中。

我希望创建一个新的代理对象,每个测试都有一个干净的数据库,所以我在 conftest.py 文件中使用了一个 pytest 夹具。

    @pytest.fixture
    def agent():
        agent=Agent(parm1="param1",...)
        return agent

我无法从数据库中正确“解除绑定”并在我的第二次测试中出现此错误:

pony.orm.core.BindingError: Database object was already bound to SQLite provider

我想要一些关于最佳方式的建议。 谢谢。

【问题讨论】:

    标签: python pytest ponyorm


    【解决方案1】:

    我认为对于您的情况,您应该为实体创建一些工厂并为每个设置创建新的数据库对象。

    def define_entities(db):
        class Student(db.Entity):
            ...
    
        class Group(db.Entity):
            ...
    

    那么你可以做类似的事情

    def setup_db(filepath=None):
        db = Database()
        if filepath:
            db.bind(provider="sqlite", filename=filepath, create_db=True)
        else:
            db.bind(provider="sqlite", filename=":memory:", create_db=True)
        define_entities(db)
        db.provider.converter_classes.append((Enum, EnumConverter))
        db.generate_mapping(create_tables=True)
    

    【讨论】:

    • 感谢您的回答,但如果我这样做,我将无法在代码的其他部分引用模型,我可能会遗漏一些东西?
    • @peteretep 所有实体都可以从db.entities获得
    【解决方案2】:

    查看 Pony 代码似乎应该足以清除 Database 实例的 provider 属性以使其新鲜以便再次绑定。

    如果您 yield Agent 而不是从您的夹具中返回它,那么您在 yield 语句之后放置的所有内容都将作为夹具拆卸代码运行。

    【讨论】:

    • 您还需要清除schemadb.provider = db.schema = None 为我工作。
    【解决方案3】:

    previous answer from zgoda 几乎可以工作。除了db.provider,还需要清除db.schema。我的建议是你创建另一个函数:

    def unbind_db():
        db.provider = db.schema = None
    

    你的灯具应该是这样的:

    @fixture
    def database() -> None:
        setup_db()
        ...
        try:
           yield
        finally:
           unbind_db()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多