Reputation: 316
I have some nested google.proto.message objects and am trying to override an attribute deep inside the parent model when making test data with factoryboy. Some of the children messages are created with a lazy_attribute which contains logic to populate them using other objects.
I've reproduced the issue I'm having in factoryboy with a much simpler example using attrs
models.
class BookFactory(factory.Factory):
class Meta:
model = models.Book
class Params:
num_pages = 10
@factory.lazy_attribute
def pages(self):
return PageFactory.build_batch(self.num_pages)
book = BookFactory.build(
num_pages=3,
pages__0__content='mypage0',
)
# This fails. How do I override pages[0].content with a BookFactory attribute?
assert book.pages[0].content == 'mypage0'
I have an running example of the failure at https://repl.it/@TomGoBravo/lazyattributesubfactory
Thank you for any suggestions you have!
Upvotes: 0
Views: 926
Reputation: 41
You can use a post_generation method to control the number of items created as well as the attributes of the underlying model.
class BookFactory(factory.Factory):
class Meta:
model = models.Book
@factory.post_generation
def pages(self, create, extracted, **kwargs):
if not create:
return
num_pages = kwargs.get('num_pages', 0)
if num_pages > 0:
book.pages = <---code goes here--->
book = BookFactory.build(
pages__num_pages=3,
pages__0__content='mypage0',
)
Upvotes: 0
Reputation: 3589
The best way would be with a SubFactory
wrapped in factory.List
, but you'll lose the ability to adjust the length of said list:
class BookFactory(factory.Factory):
class Meta:
model = models.Book
pages = factory.List([
factory.SubFactory(PageFactory),
factory.SubFactory(PageFactory),
factory.SubFactory(PageFactory),
])
Otherwise, you'd have to implement (and contribute !) some form of SubFactoryList
, similar to the existing RelatedFactoryList
.
Upvotes: 1