2014-07-05 7 views
6

Próbuję uruchomić następujący Django unittest:Testowanie kilku IntegrityErrors w tym samym Django unittest testowym przypadku

class MyModelTests(TestCase): 
    def test_failed_duplicate(self): 
     m = MyModel.objects.create(a='a', b='a') 
     with self.assertRaises(IntegrityError): 
      MyModel.objects.create(a='a', b='b') 
     with self.assertRaises(IntegrityError): 
      MyModel.objects.create(a='a', b='c') 
     with self.assertRaises(IntegrityError): 
      MyModel.objects.create(a='a', b='d') 

Istnieje kilka testów, aby wszyscy nie ze względu na złamanie ograniczenia unikatowości na polu a. (. Mam ukrywane twierdzenia trochę, ale wszystkie one przetestować różne wartości a że nie uda)

Jednak po uruchomieniu pojawia się:

Traceback (most recent call last): 
    File "...", line 21, in test_failed_duplicate 
    MyModel.objects.create(a='a', b='c') 
TransactionManagementError: An error occurred in the current transaction. You can't execute queries until the end of the 'atomic' block. 

Czego mi brakuje?

Odpowiedz

15

(... Ach, tak wpadłem na ten sam jakiś czas temu i złożone a ticket o nim może znaleźć powstałej dyskusji ciekawe)

powód widzisz to, że:

  1. Ze względów wydajnościowych w ramach transakcji przeprowadzane są testy TestCase.
  2. Podniesienie IntegrityError zepsuć bieżącą transakcję (dokładniej, bieżący blok atomowy), niezależnie od tego, czy został złapany, czy nie.

Więc w kodzie, pierwszy assertRaises działa poprawnie, ale ponieważ IntegrityError podniesiono transakcja staje się zepsuty. Podczas próby uzyskania dostępu do bazy danych następnym create() otrzymasz numer TransactionManagementError.

Istnieją dwa możliwe rozwiązania:

  1. Dziedziczenie z TransactionTestCase zamiast TestCase. Wykorzystuje to obcinanie tabeli zamiast transakcji do resetowania bazy danych, więc nie będziesz mieć tego problemu.
  2. Przeprowadź każdy z testów create() wewnątrz nowego bloku atomowego. Możesz zobaczyć przykład w bilecie i szerszy opis w the docs.
+0

Idealnie! Dzięki :) –

+0

Bardzo przydatne. Dzięki. – freethebees