How do I test a Django CreateView?

烈酒焚心 提交于 2019-12-07 17:38:40

问题


I want to practice testing on Django, and I have a CreateView I want to test. The view allows me to create a new post and I want to check if it can find posts without a publication date, but first I'm testing posts with published date just to get used to syntax. This is what I have:

import datetime
from django.test import TestCase
from django.utils import timezone
from django.urls import reverse
from .models import Post, Comment

# Create your tests here.
class PostListViewTest(TestCase):

    def test_published_post(self):
        post = self.client.post('/post/compose/', {'author':"manualvarado22", 'title': "Super Important Test", 'content':"This is really important.", 'published_date':timezone.now()})
        response = self.client.get(reverse('blog:post_detail'))
        self.assertContains(response, "really important")

But I get this:

django.urls.exceptions.NoReverseMatch: Reverse for 'post_detail' with no 
arguments not found. 1 pattern(s) tried: ['post/(?P<pk>\\d+)/$']

How do I get the pk for that newly created post?

Thank you!


回答1:


You can get it directly from the database.

Note, you shouldn't call two views in your test. Each test should only call the code it is actually testing, so this should be two separate views: one to call the create view and assert that the entry is in the db, and one that creates an entry directly and then calls the detail view to check that it displays. So:

def test_published_post(self):
    self.client.post('/post/compose/', {'author':"manualvarado22", 'title': "Super Important Test", 'content':"This is really important.", 'published_date':timezone.now()})
    self.assertEqual(Post.objects.last().title, "Super Important Test")

def test_display_post(self):
    post = Post.objects.create(...whatever...)
    response = self.client.get(reverse('blog:post_detail', pk=post.pk))
    self.assertContains(response, "really important")



回答2:


What you wanna do with testing is using the relyable Django Databse API for recevieng the created data and see if your view represents this data.

As you only create 1 model instance and save it. You may obtain its pk via

model_pk = Post.objects.get(author="manualvarado22").pk

This pk then should be inserted into your url as the Exception states.

But i also recommend abseconded test, where you directly check if the newly created "Post" exists in the DB via django model API. Edit:

When testing, django or the test Module you are using, creates a clean database only for testing and destroys it after the test-run. So if you want to acces a User while testing you must have created the user in your Test setup or in the Test method itself. Otherwise the Usertable would be empty.




回答3:


I was finally able to solve the issue thanks to your great answers as well as some extra SO research. This is how the test looks like:

def test_display_no_published_post(self):
        test_user = User.objects.create(username="newuser", password="securetestpassword")
        post = Post.objects.create(author=test_user, title="Super Important Test", content="This is really important.")
        response = self.client.get(reverse('blog:post_detail', kwargs={'pk':post.pk}))
        self.assertEqual(response.status_code, 404)

And this are the create and detail views:

class PostDetailView(DetailView):
    model = Post

    def get_queryset(self):
        return Post.objects.filter(published_date__lte=timezone.now())

class PostCreateView(LoginRequiredMixin, CreateView):
    login_url = '/login/'
    redirect_field_name = 'blog/post_detail.html'

    form_class = PostForm
    model = Post


来源:https://stackoverflow.com/questions/47111777/how-do-i-test-a-django-createview

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!