2010-01-10 6 views
49

Ich habe Django-Code, der mit Anfrage Objekte oder Benutzerobjekte interagiert. Zum Beispiel so etwas wie:Wie Mock Benutzer und Anforderungen in Django

foo_model_instance = models.get_or_create_foo_from_user(request.user) 

Wenn du mit dem django Python-Shell oder in einem Unittest testen würden, was würde passieren Sie da drin? Hier genügt ein User-Objekt, aber die Notwendigkeit eines Schein-Request-Objekts kommt auch häufig vor.

Für die Schale oder für Unittests:

  • Wie wollen Sie Mock-Benutzer?
  • Wie verspotten Sie Anfragen?
+2

"Sie verwenden dieses Wort, aber ich glaube nicht, es bedeutet, was Sie denken, es bedeutet ... "Ich denke du meinst" Modell ". –

+7

@Mike: Es klingt lustig, aber ich denke, er hat es richtig gemacht. @pax: Beat mich an die Pointe :( – mpen

+5

ich ... ich muss gestehen, dass ... in der Stille meines Zimmers ... spät in der Nacht ... ich ... ja, ja! Ich verspotte Benutzer Alle! @perrierism: Wir machen uns nicht über dich lustig, wir genießen gerade deine wunderbare Wortwahl. –

Antwort

48

Für Anfrage würde ich RequestFactory mit Django enthalten.

from django.test.client import RequestFactory 
rf = RequestFactory() 
get_request = rf.get('/hello/') 
post_request = rf.post('/submit/', {'foo': 'bar'}) 

für Benutzer, würde ich django.contrib.auth.models verwenden.Benutzer wie @ozan vorgeschlagen und vielleicht mit factory boy für die Geschwindigkeit (mit Fabrik Jungen können Sie nicht in DB speichern zu speichern)

+0

Dies ist definitiv die richtige Antwort jetzt, dass RequestFactory verfügbar ist. Mit der Anerkennung von Ozans Antwort (das Instanziieren der realen Objekte ist ausreichend und wünschenswert). Ich habe Factory Boy nicht benutzt, aber wenn es der Qualität von Rail's Factory Girl nahe kommt, sieht es so aus, als ob es eine ausgezeichnete Wahl wäre. – Purrell

+0

Beste Lösung, die für mich in einem Django-Migrationsskript funktioniert hat. In der aktuellen Version muss jedoch 'request.user' eingestellt sein. Um diese Anfrage wie eine normale Ansicht zu verwenden, ist es schön, in der Bereit-Anfrage 'request.csrf_processing_done = True' zu ​​haben (um die CSRF-Prüfungen zu bestehen). – garmoncheg

38

Wie verspotten Sie Benutzer?

Initialisieren Sie ein Objekt django.contrib.auth.models.User. User.objects.create_user macht das einfach.

Wie wollen Sie Mock-Anfragen?

Initialisieren Sie ein django.http.HttpRequest Objekt.

Natürlich gibt es Verknüpfungen, je nachdem, was Sie tun möchten. Wenn Sie nur ein Objekt mit einem user Attribut benötigen, das auf einen Benutzer verweist, erstellen Sie einfach etwas (irgendetwas) und geben Sie ihm dieses Attribut.

+5

+1: Mock? Warum Mock? Benutze das echte Ding. –

+1

@ S.Lott es ist gut zu bedienen Manchmal ist es echt, aber es endet sehr langsam, wenn Ihr Projekt wächst.Es ist schön, Mock-Tests zu haben, die Sie in ein paar Sekunden anstatt in ein paar Minuten ausführen können. –

+0

@TM: Vielleicht stimmt das im Allgemeinen. Aber der Django-Client ist wirklich schnell Hast du eine Alternative und einige Benchmarks, um die Zeitersparnis aufzuzeigen? –

3

Sie müssen keine Benutzer verspotten, wie Sie nur eine in Ihrem Test erstellen können - die Datenbank zerstört wird, nachdem der Test abgeschlossen ist.

Um Mock-Anfragen verwenden this snippet von Simon Willison.

+0

Während ich zustimme, können Sie in der Regel mit der Erstellung von Benutzern für Ihre Tests - es gibt Zeiten, die Sie nicht wollen - oder dies ist außerhalb der Zuständigkeit des Tests. Wenn ich versuche, diese Berechtigung zu verweigern, wenn eine Hilfsmethode False zurückgibt, ist es falsch für mich, das mit der Datenbank zu koppeln. Diese Hilfsmethode existiert, WEIL ich nichts über die Datenbankdarstellung wissen möchte. – yarbelk

6

Sie können entweder eigene Mocks rollen, wie Anurag Uniyal vorgeschlagen hat, oder Sie können einen Mockframework verwenden.

Als Antwort auf diejenigen, sagen Sie einen normalen Benutzer einfach erstellen können, wie Sie in Django sowieso würde ... ich diese besiegt den Punkt des Unit-Test vorschlagen würde. Ein Komponententest sollte die Datenbank nicht berühren, aber wenn Sie einen Benutzer erstellen, haben Sie die Datenbank geändert, weshalb wir uns eine solche vorstellen möchten.

+0

Wie Daniel bereits erwähnt hat, erstellt der Test Runner dann eine Testdatenbank für Sie, so dass Sie sich darüber keine Gedanken machen müssen. – ozan

+3

Außer wenn Sie die Datenbank verwenden, ist es kein Unit-Test mehr. Es kann immer noch ein perfekt gültiger Integrationstest sein, aber es ist kein Komponententest. –

+1

Das Problem besteht darin, dass das Erstellen und Löschen einer Datenbank Zeit kostet. Ich möchte im Handumdrehen Tausende von Tests durchführen, jedes Mal, wenn ich etwas ändere. Ich möchte nicht eine Datenbank und eine Anwendungsinstanz aufstellen, um meine Tests auszuführen. –