Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using factory_boy with SQLAlchemy and class methods

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?

like image 438
pfctdayelise Avatar asked Jul 09 '13 05:07

pfctdayelise


1 Answers

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()
like image 131
Matthew Graves Avatar answered Oct 01 '22 12:10

Matthew Graves