Django / Python unittesting: Wie Force Exception of Try / Except Block zu erzwingen

Gibt es irgendeine Möglichkeit, den Auslösungsblock zu erzwingen, damit ich die Fehlermeldungen / Handhabung mit Unit-Tests überprüfen kann? Beispielsweise:

Views.py

def get_books(request): ... try: book = Books.objects.get_or_create(user=request.user) except: messages.error(request, 'Unable to create new book!') return HttpResponseRedirect(reverse('my_books')) # more try/except cases 

Also in diesem Beispiel könnte ich versuchen, einen ORM-Fehler zu simulieren, oder ich kann versuchen, einen ungültigen Benutzer für diesen Fall zu senden. Aber gibt es einen allgemeinen Weg, um Ausnahmen zu werfen (ich bin offen für die Verwendung von Bibliotheken) ? Mock zum Beispiel. Oder gibt es noch eine andere Methode, um unittest zu benutzen, um Ausnahmen zu erzwingen? Offensichtlich gibt es viele Versuche / außer Blöcke während des Codes, also suche ich irgendeine Hilfe.

One Solution collect form web for “Django / Python unittesting: Wie Force Exception of Try / Except Block zu erzwingen”

Sie können unittest.mock , um es zu tun. Du sollst das Books.objects Objekt von patch.object und side_effect , um Exception zu heben. Ein vollständiger Test für Ihre Methode Ausnahme Verhalten sollte:

 import unittest from unittest.mock import patch, ANY from django.test.client import RequestFactory class TestDjango(unittest.TestCase): @patch("your_module.messages") @patch("your_module.HttpResponseRedirect") def test_get_books_exception(self,mock_redirect,mock_messages) r = RequestFactory().get('/I_dont_konw_how_to_build_your_request/') objs = Books.objects with patch.object(objs,"get_or_create", side_effect=Exception()): self.assertIs(get_books(r),mock_redirect.return_value) mock_messages.error.assert_called_with(r, ANY) mock_redirect.assert_called_with(reverse('my_books')) 

Ich habe ANY die ANY entfernt. Ich bin mir nicht sicher, was du in deinem Code testen willst (komplettes Verhalten oder einfach weiterleiten …), trotzdem habe ich ein komplettes Beispiel geschrieben.


Wenn Ihr Projekt keine Legacy-Arbeit ist, sollten Sie Ihre Methode (und die neuen Django-ORM-Anrufe) im TDD-Stil umschreiben, wo Sie zB eine _get_books_proxy() Funktion haben, die nur die Django ORM-Methoden aufruft:

 def _get_books_proxy(request): return Books.objects.get_or_create(user=request.user) 

Und jetzt Patch _get_books_proxy() direkt von patch Dekorateur als:

 @patch("your_module.messages") @patch("your_module.HttpResponseRedirect") @patch("your_module._get_books_proxy", side_effect=Exception()) def test_get_books_exception(self,mock_get_book, mock_redirect, mock_messages) r = RequestFactory().get('/I_dont_konw_how_to_build_your_request/') self.assertIs(get_books(r),mock_redirect.return_value) mock_messages.error.assert_called_with(r, ANY) mock_redirect.assert_called_with(reverse('my_books')) 

Darüber _get_books_proxy() kann das Verhalten von _get_books_proxy() durch Patching von Books und übergeben eines einfachen Mock() :

 @patch("your_module.Books") def test__get_books_proxy(self,mock_books): r = Mock() self.assertIs(mock_books.objects.get_or_create.return_value, your_module._get_books_proxy(r)) mock_books.objects.get_or_create.assert_called_with(user=r.user) 

Jetzt hast du einen Sentinel, der dir nachgeben kann, wenn dein kritisches Punktverhalten geändert wird.

Ich entschuldige mich, wenn du Fehler findest (ich kann es nicht testen) … aber ich hoffe die Idee ist klar.

  • Wie überschreibt man ein Zeitstempelfeld für Unit-Testzwecke?
  • Prüfen Sie, ob eine Funktion eine Warnung mit Nasentests auslöst
  • Django Benutzer Setup für Nase Tests
  • Wie man Argumente an ein UnitTest ohne globale Variablen sendet
  • Einheit testet ganze Projekthierarchie in Python mit unittest in pydev
  • Wie kann ich einen Redis-Client in Python verspotten?
  • Nase nicht laufen Django Dokthen
  • Verwalten von Protokollen / Warnungen in Python-Erweiterungen
  • Python ist die beste Programmiersprache der Welt.