Using factory_boy with SQLAlchemy and class methods
Asked Answered
T

1

7

I am working on a Pyramid app with SQLAlchemy as the ORM. I am trying to test a model with a class method:

# this is essentially a global used by all the models
Session = scoped_session(sessionmaker(autocommit=False))

class Role(Base):
    __tablename__ = 'role'

    id = sa.Column(sa.types.Integer, primary_key=True)
    name = sa.Column(sa.types.Text, unique=True, nullable=False)

    def __init__(self, **kwargs):
        super(Role, self).__init__(**kwargs)

    @classmethod
    def find_all(self):
        return Session.query(Role).order_by(Role.name).all()

I am using factory_boy to test and here is how I am trying to set up my testing factory:

import factory
from factory.alchemy import SQLAlchemyModelFactory
from sqlalchemy.orm import scoped_session, sessionmaker
from zk.model.meta import Base
from zk.model.role import Role

session = scoped_session(sessionmaker())
engine = create_engine('sqlite://')
session.configure(bind=engine)
Base.metadata.create_all(engine)

class RoleFactory(SQLAlchemyModelFactory):
    FACTORY_FOR = Role
    FACTORY_SESSION = session

However when I try to call RoleFactory.find_all() in a test, I get an error: E UnboundExecutionError: Could not locate a bind configured on mapper Mapper|Role|role, SQL expression or this Session

I tried monkeypatching meta and replacing that global Session with my session, but then I get this error: E AttributeError: type object 'RoleFactory' has no attribute 'find_all'

I tried calling RoleFactory.FACTORY_FOR.find_all() but then I get the same UnboundExecutionError.

Do I need to do something else for factory_boy to know about the class method?

Teague answered 9/7, 2013 at 5:54 Comment(0)
M
4

This might be too obvious, but it seems that what you've got is a RoleFactory instance, when you need a Role instance, the factory wouldn't have access to any classmethods since it's not a child of the class. Try doing this and seeing what happens:

role = RoleFactory.build()
roles = role.find_all()
Montiel answered 17/7, 2013 at 6:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.