Search code examples
djangodjango-rest-frameworkfactorydjango-testingdjango-tests

Django FactoryBoy TestCase handling nested object creation


I am trying to write TestCase with django factory and this lill bit advance testcase writing..

This is my models.py below:

class Author(models.Model):
    name = models.CharField(max_length=25)

    def __str__(self):
        return self.name

class Book(models.Model):
    author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name='author')
    title = models.CharField(max_length=200)
    body = models.TextField()

    def __str__ (self):
        return self.title

and this is my tests.py below

from django.test import TestCase
from library.models import Author, Book
import factory

# Create factory for model
class AuthorFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = Author
    name = 'author name'

class BookFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = Book
    author = factory.SubFactory(AuthorFactory)
    title = 'i am title'
    body = 'i am body'


# Start TestCase here

class TestSingleBook(TestCase):
    def setUp(self):
        self.author = AuthorFactory.create_batch(
            10,
            name='Jhon Doe'
        )
        self.book = BookFactory.create_batch(
            author=self.author
        )

    def test_single_book_get(self):
        # compare here

above code, my testcase class is class TestSingleBook(TestCase): i hope you noticed it..

I want to create 10 Author and create 10 book with those 10 Author, and then i will compare it in assertEqual

if i create multiple book with single author, i can craft the test easily but i dont want it...

My Problem is Nested/Multiple...

Create multiple author and then create multiple book with those author...

is there anyone who solved these kind of problem before?

Can anyone help me in this case? if you dont get above all these, feel free to ask me regarding this..


Solution

  • Not really sure if this is what you want, because I cannot really understand what you are going to compare in the test case. But for your statement of creating 10 authors with 10 books, one way to do such creation is simply using a for loop:

    self.author = AuthorFactory.create_batch(10, name='Jhon Doe')
    for author in self.author:
        BookFactory.create(author=author)
    

    Of course this will not gain the efficiency of using create_batch. If you still want to use create_batch anyway, you can use django ORM relation representation:

    BookFactory.create_batch(
        10,
        author__name='Jhon Doe',
        title=<your title>,
        body=<your body>)
    

    Note that there is no need to call AuthorFactory.create() since you have already declare author to be a SubFactory in BookFactory. The second code will create 10 Book objects with 10 different Author objects, and all the Author objects all has the same name of 'Jhon Doe'.