Ich versuche Einheitentests für eine Django-App zu schreiben, die viele Datetime-Operationen ausführt. Ich habe mock installiert, um die timezone.now
von affe patch django für meine Tests zu installieren.
Obwohl ich timezone.now
erfolgreich verkünden kann, wenn es normal aufgerufen wird (tatsächlich ruft timezone.now()
in meinem Code auf, kann ich es nicht für Modelle vortäuschen, die mit DateTimeField
mit default=timezone.now
erstellt wurden.
Ich habe ein User
-Modell, das Folgendes enthält:
Mein Komponententest sieht so aus:
%Vor% assertEquals(user.modified, dt)
wird übergeben, aber assertEquals(user.timestamp, dt)
nicht.
Wie kann ich timezone.now
vortäuschen, so dass auch default=timezone.now
in meinen Modellen die Mockzeit erstellt?
Bearbeiten
Ich weiß, dass ich einfach meinen Einheitentest ändern könnte, um ein timestamp
meiner Wahl zu übergeben (wahrscheinlich erzeugt durch das verspottete timezone.now
) ... Neugierig, wenn es einen Weg gibt, der das jedoch vermeidet.
Ich bin gerade selbst auf dieses Problem gestoßen. Das Problem besteht darin, dass die Modelle geladen werden, bevor der Zeitzonenmodul von mock gepatcht wurde. Zu dem Zeitpunkt, zu dem der Ausdruck default=timezone.now
ausgewertet wird, setzt er default
kwarg auf die echte Funktion timezone.now
.
Die Lösung ist die folgende:
%Vor% Hier ist eine Methode, die Sie verwenden können, ohne dass Sie Ihren Nicht-Test-Code ändern müssen. Patchen Sie einfach die default
Attribute der Felder, die Sie beeinflussen möchten. Zum Beispiel -
Sie können Hilfsfunktionen schreiben, um dies weniger ausführlich zu machen. Zum Beispiel der folgende Code -
%Vor%würde Sie schreiben lassen -
%Vor%Sie können auch Helferkontextmanager schreiben, um mehrere Felder gleichzeitig zu patchen.
Sieht so aus, als ob Sie die Zeitzone im patchen falscher Ort.
Angenommen, Ihr User
-Modell lebt in myapp\models.py
und Sie möchten save()
in dieser Datei testen. Das Problem ist, dass wenn Sie from django.utils import timezone
an der Spitze, importiert es es von django.utils
. In Ihrem Test patchen Sie timezone
lokal, und das hat keine Auswirkungen auf Ihren Test, da das Modul myapp\models.py
bereits einen Verweis auf das echte timezone
hat und es so aussah, als hätte unser Patch keinen Effekt.
Versuchen Sie timezone
von myapp\models.py
zu patchen, etwas wie:
Es gibt einen anderen einfachen Weg, um das oben genannte zu tun.
%Vor%Dies ist der beste Weg, um timezone.now zu verspotten.
Tags und Links python django unit-testing mocking python-mock