Comment importer l'exception Django DoesNotExist?

122

J'essaye de créer un UnitTest pour vérifier qu'un objet a été supprimé.

from django.utils import unittest
def test_z_Kallie_can_delete_discussion_response(self):
  ...snip...
  self._driver.get("http://localhost:8000/questions/3/want-a-discussion") 
  self.assertRaises(Answer.DoesNotExist, Answer.objects.get(body__exact = '<p>User can reply to discussion.</p>'))

J'obtiens toujours l'erreur:

DoesNotExist: Answer matching query does not exist.
BryanWheelock
la source
Sans rapport avec ma réponse ci-dessous, cet appel get () supprime-t-il la réponse en question? Si tel est le cas, cela devrait vraiment être un DELETE, pas un GET.
Steve Jalim

Réponses:

136

Vous n'avez pas besoin de l'importer - comme vous l'avez déjà écrit correctement, DoesNotExistc'est une propriété du modèle lui-même, dans ce cas Answer.

Votre problème est que vous appelez la getméthode - ce qui déclenche l'exception - avant qu'elle ne soit transmise assertRaises. Vous devez séparer les arguments de l'appelable, comme décrit dans la documentation unittest :

self.assertRaises(Answer.DoesNotExist, Answer.objects.get, body__exact='<p>User can reply to discussion.</p>')

ou mieux:

with self.assertRaises(Answer.DoesNotExist):
    Answer.objects.get(body__exact='<p>User can reply to discussion.</p>')
Daniel Roseman
la source
1
Bonne réponse, seul le premier des extraits ci-dessus sera intercepté comme syntaxe invalide (au moins par Python 2.7)., Devrait être self.assertRaises(Answer.DoesNotExist, Answer.objects.get, body__exact = '<p>User can reply to discussion.</p>')- c'est-à-dire avec getles arguments de s ajoutés en tant qu'arguments kw individuels, pas à l'intérieur d'un ().
Martin B.
1
Augh, bien sûr! Je me sens comme Dorothy ici. Je cherchais haut et bas, seulement pour constater que c'était avec moi tout le temps!
Nick S
Python 3.6 / Django 2.2 seule la withsolution a fonctionné pour moi.
theruss
183

Vous pouvez également importer ObjectDoesNotExistdepuis django.core.exceptions, si vous souhaitez une méthode générique indépendante du modèle pour intercepter l'exception:

from django.core.exceptions import ObjectDoesNotExist

try:
    SomeModel.objects.get(pk=1)
except ObjectDoesNotExist:
    print 'Does Not Exist!'
Chris Pratt
la source
10

DoesNotExistest toujours une propriété du modèle qui n'existe pas. Dans ce cas, ce serait le cas Answer.DoesNotExist.

defrex
la source
3

Une chose à surveiller est que le deuxième paramètre assertRaises doit être un appelable - pas seulement une propriété. Par exemple, j'ai eu des difficultés avec cette déclaration:

self.assertRaises(AP.DoesNotExist, self.fma.ap)

mais cela a bien fonctionné:

self.assertRaises(AP.DoesNotExist, lambda: self.fma.ap)
Xiong Chiamiov
la source
3
self.assertFalse(Answer.objects.filter(body__exact='<p>User...discussion.</p>').exists())
Chris
la source
Cela ne répond pas exactement à la question demandée. Mais c'est toujours une belle solution, offrant une approche différente pour obtenir le résultat souhaité.
cezar
0

C'est ainsi que je fais un tel test.

from foo.models import Answer

def test_z_Kallie_can_delete_discussion_response(self):

  ...snip...

  self._driver.get("http://localhost:8000/questions/3/want-a-discussion") 
  try:
      answer = Answer.objects.get(body__exact = '<p>User can reply to discussion.</p>'))      
      self.fail("Should not have reached here! Expected no Answer object. Found %s" % answer
  except Answer.DoesNotExist:
      pass # all is as expected
Steve Jalim
la source