Search code examples
django-testingdjango-tests

Django returns empty QuerySet in the tests


I'm trying to make a test for this view:

def author_detail(request, pk):
    author = get_object_or_404(Author, pk=pk)
    blog = author.blog_set.all()

    paginator = Paginator(blog, 1)

    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)

    context = {
        'author': author,
        'page_obj': page_obj,
    }

    return render(request, 'blog/author_detail.html', context=context)

The view is working normally. My problem is when I'm going to try to test this view. Here my test:

class AuthorDetailViewTest(TestCase):
    def setUp(self):
        user = User.objects.create(username='user01', password='123456')

        self.author_instance = Author.objects.create(
            user=user, date_of_birth='1998-09-08', bio='I am user01')

        topic = Topic.objects.create(name='Testing')

        Blog.objects.create(title='My blog', content="It's my blog")
        Blog.author = self.author_instance
        Blog.topic = topic

    # The author.blog_set.all() are returning an empty QuerySet
    # This problem are only happening in the tests, not in the view
    def test_pagination_first_page(self):
        response = self.client.get(
            reverse('author-detail', kwargs={'pk':self.author_instance.pk}))
        self.assertEqual(len(response.context['page_obj']), 1)

The result are:

FAIL: test_pagination_first_page (blog.tests.test_views.AuthorDetailViewTest)
-------------------------------------------------------------------
Traceback (most recent call last):
   File "/home/carlos/problem/venv_01/the_blog/blog/tests/test_views.py", line 189,in test_pagination_first_page
       self.assertEqual(len(response.context['page_obj']), 1)
AssertionError: 0 != 1
----------------------------------------------------------------------

The len(response.context['page_obj']) is equal 0. It should be at least 1, because I created one Blog object. When I print the QuerySet of author.blog_set.all(), the returned QuerySet are empty (<QuerySet []>). I think that the problem is in the creation of the Blog model, because the author and topic fields are ManyToManyField.

As I mentioned before, my problem is in the test, not in the view. The view is working normally.


Solution

  • The last 3 lines of the following code snippet have some issues:

        def setUp(self):
            user = User.objects.create(username='user01', password='123456')
    
            self.author_instance = Author.objects.create(
                user=user, date_of_birth='1998-09-08', bio='I am user01')
    
            topic = Topic.objects.create(name='Testing')
    
            Blog.objects.create(title='My blog', content="It's my blog")
            Blog.author = self.author_instance
            Blog.topic = topic
    
    • The blog object is created but never returned/fetched
    • Blog model is being used to connect author and topic. Instead, the blog object should be used.
    • Author and Topic are M2M on Blog. The new objects should be added via add method. See How to add data into ManyToMany field? for additional context.