2016-05-27 4 views
2

Ich bin mit einem seltsamen Fehler konfrontiert, in dem ein Django-Test, den ich geschrieben habe, um die Antwort einer Ansicht zu testen, mir nicht das erwartete Verhalten gibt.Testclient wirft nicht erwarteten 404-Fehler

Betrachten Sie das folgende Modell für eine einfache Blogging-Anwendung:

class Post(models.Model): 
    """Represents a Post in the blogging system.""" 

    # is the post published or in draft stage? 
    STATUS_CHOICES = (
     ('draft', 'Draft'), 
     ('published', 'Published'), 
     ('deleted', 'Deleted'), 
    ) 

    # the default mode for posts 
    DRAFT = STATUS_CHOICES[0][0] 

    title = models.CharField(max_length=250, null=True) 
    slug = models.SlugField(max_length=200, blank=True) 
    text = models.TextField(null=True) 
    last_modified = models.DateTimeField(default=timezone.now) 
    date_published = models.DateTimeField(default=timezone.now, null=True) 
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default=DRAFT) 

    category = models.ForeignKey('Category', null=True) 
    author = models.ForeignKey('Author', null=True) 

    class Meta: 
     ordering = ('-date_published',) 

    @property 
    def truncated_text(self): 
     if len(self.text) > 200: 
       return '{} . . .'.format(self.text[0:300]) 
     else: 
       return self.text 

    def publish(self): 
     self.date_published = timezone.now() 
     self.status = 'published' 
     self.save() 

    def save(self, *args, **kwargs): 
     # Set slug only on new posts 
     if not self.id: 
      self.slug = slugify(self.title) 

     self.last_modified = timezone.now() 
     super().save(*args, **kwargs) 

    def __str__(self): 
     return self.title 

Hier ist die Ansicht (man kann sehen, dass ich das Beharren auf veröffentlichten Beiträge nur immer):

def post_view(request, slug): 
    post = get_object_or_404(Post, slug=slug, status='published') 
    return render(request, 'blog/single_post.html', {'post': post}) 

Hier ist die URL Eintritt:

url(r'^blog/(?P<slug>[-\w]+)/$', blog_view.post_view, name='single_post'), 

Und schließlich, hier ist der Test:

class TestBlogViews(TestCase): 
    """Class to test the views of our blog app""" 

    def setUp(self): 
     """Make sure we have an environment in which to render the templates""" 

     # An author 
     self.author = Author() 
     self.author.name = 'Ankush' 
     self.author.short_name = 'ank' 
     self.author.save() 

     # A category 
     self.cat = Category() 
     self.cat.name = 'Programming' 
     self.cat.save() 

     # A post 
     self.post = Post() 
     self.post.title = 'Dummy title' 
     self.post.text = 'Dummy text that does nuffin' 
     self.post.author = self.author 
     self.post.category = self.cat 

     setup_test_environment() 
     self.client = Client() 

    def test_unpublished_post_raises_404(self): 
     self.post.save() 
     response = self.client.get(reverse('single_post', args=('dummy-title',))) 
     self.assertEqual(response.status_code, 404) 

Also im Grunde versagt mein Test, weil ich 200 != 404 bekommen. Ich lief auch die Post API von Shell, und bekam eine DoesNotExist bei der Suche nach status = 'published' auf einen Beitrag, der nur die save()-Methode genannt hatte. Ich habe auch die response.content in meinem Test gedruckt, und es enthält den benutzerdefinierten 404 Vorlageninhalt. Warum wirft es nicht 404, wenn das Objekt eindeutig nicht existiert? Irgendetwas stimmt nicht mit get_object_or_404()?

P.S. Bitte lassen Sie mich wissen, wenn Sie weitere Codeschnipsel benötigen.

+0

Welche Testdatenbank verwenden Sie? Können Sie sicherstellen, dass die Datenbank in der Tat sauber ist, ohne vorherige Daten, die die Situation irgendwie durcheinander bringen? –

+0

@ShangWang Nun, ich verlasse mich auf die Testdatenbank, die Django erstellt (usong MariaDB 10.1, übrigens). Zerstört und rekonstruiert Django nicht jedes Mal Dinge? – dotslash

+0

@ShangWang Okay, ich konnte etwas verbessern. Ich musste eigentlich einen neuen 'Client()' für jede Methode erstellen. Auf diese Weise erhalte ich jetzt den benutzerdefinierten Inhalt der 404-Seite, aber der Antwortcode ist immer noch "200". Komisch! : - | – dotslash

Antwort

1

In Ordnung, ich konnte es herausfinden. Es stellte sich meine benutzerdefinierte 404 Aussicht wurde vermasselt:

Es war:

def not_found(request): 
    return render(request, 'ankblog/not_found.html') 

So natürlich der Statuscode war 200. Es wurde behoben, indem es in return render(request, 'ankblog/not_found.html', status=404) geändert wurde.

Ich finde es aber lustig. Ich hätte gedacht, dass die benutzerdefinierte 404 einen 404-Fehler automatisch ausgelöst hätte.

Verwandte Themen