4

I am writing a unit test for SQLAlchemy model class with one-to-many relationship but am not able to add a mocked object into the collection.

Classes under test:

class PCLRun(Base):
    __tablename__ = 'pcl_runs'
    id = Column(Integer, primary_key=True)
    ...
    files = relationship("PCLOutputFile", backref='pcl_run')

class PCLOutputFile(Base):
    __tablename__ = 'pcl_output_files'
    id = Column(Integer, primary_key=True)
    ...
    pcl_run_id = Column(Integer, ForeignKey('pcl_runs.id'))

Test code:

class PCLRunTests(unittest.TestCase):
    def test_foo(self):
        file_mock = mock.Mock()
        pcl_run = PCLRun()
        pcl_run.files.append(file_mock)
        ...

Appending the mock object raises an exception:

TypeError: 'Mock' object has no attribute '__getitem__'

Is there any way to unit test the class containing the relationship by adding mocks into it while keeping the collection behave like a simple list?

I'm using mock 1.0.1 and sqlalchemy 0.8.2.

1 Answers1

0

I think think the issue is that the PCLRun instance is expecting an instance of the PCLOutputFile class as an argument to the append method. Your Mock instance has none of the same attributes so it raises an error when it tries the __getitem__ method.

You could try take advantage of Python use of duck-typing to create a Mock object with all the attributes of a PCLOutputFile file but that might prove difficult depending on how much inherited metadata beyond the column values the query needs..

Alternately, you could define setup/teardown methods/fixtures which would create real instance of the PCLOutputFile class in your test table. The nosetest module provides tools to for this type of testing pattern.

ACV
  • 1,895
  • 1
  • 19
  • 28