Rewrite model @property in Factory Boy's object factory
Asked Answered
D

3

7

I want to find a way to properly test my code with Factory Boy.

There are a model, like this:

from django.db import models

class MyModel(models.Model):
    param1 = <some field>
    param1 = <some field>
    param1 = <some field>

    @property
    def is_smth(self):
        <some complicated code that returns boolean>

There is a factory for this model:

import factory

class MyModelFactory(factory.DjangoModelFactory):
    param1 = <some value>
    param2 = <some value>
    param3 = <some value>

    # And here i need to "rewrite" property of the model
    # so that it would always return true

Can anyone help me with that? I didn't found mentions about this in factory boy's documentation, and various variants i've tried doesn't seem to work.

Declivitous answered 19/10, 2012 at 9:9 Comment(0)
M
5

As Suganthi said, you can using mock.

But I offer another solution:

 @classmethod
 def _create(cls, model_class, *args, **kwargs):   
     with mock.patch('MyModel.is_smth',
                     new_callable=mock.PropertyMock) as m:
         m.return_value = True
         return super()._create(model_class, *args, **kwargs)

Just mock property during generation models. It works on factoryboy==2.5.2

Mortimer answered 2/12, 2016 at 18:4 Comment(0)
M
2

Have you tried using mocks?

def test_is_smith(self):
    mymodel = MyModel()
    with mock.patch('MyModel.is_smith', new_callable=mock.PropertyMock) as mocked_model:
        mocked_model.return_value = True
        self.assertTrue(mymodel.is_smith)
Mutineer answered 4/6, 2013 at 9:8 Comment(0)
G
2

The suggestion of @StasEvseev didn't work in our case. I ended up leveraging the Factory Boy's post_generation hooks since our property is calculating the value based on other models/data. Hence, building the data needed by @is_smth will make it to behave/evaluate as intended when that property is called:

class MyModelFactory(factory.DjangoModelFactory):
    ...

    @factory.post_generation
    def prepare_data_for_is_smth(self, create, extracted, **kwargs):
       # Populate/build here the models/fields needed for your
       # <some complicated code that returns boolean>.

Post generation hooks are executed after creating the factory instance. You could further customize the hook's behavior by utilizing the extracted and kwargs parameters, which are passed in the factory class using the ATTR__SUBATTR format (e.g. MyModelFactory(foo__bar=SOME_VALUE).

Gangster answered 20/5, 2018 at 20:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.