Юнит-тестирование Django на предмет того, правильно ли POST-запрос обновляет экземпляр модели
Мне трудно понять, почему мой тест продолжает терпеть неудачу.
У меня есть две модели (показываю только соответствующий код):
class Listings(models.Model):
listing_instagram = models.URLField(null=True, blank=True)
listing_facebook = models.URLField(null=True, blank=True)
...
class ListingsDescription(models.Model):
listing = models.OneToOneField(Listings, on_delete=models.CASCADE)
space_description = models.TextField(max_length=1000, blank=True)
accessibility_description = models.TextField(max_length=1000, blank=True)
...
У меня есть правильно функционирующее представление, которое обрабатывает две формы (по одной форме на модель):
def some_view(request, listing_id):
listing = get_object_or_404(Listings, id=listing_id)
listing_description = listing.listingsdescription
if request.method == "POST":
form_a = ListingForm(request.POST or None, instance=listing)
form_b = ListingDescriptionForm(request.POST or None, instance=listing_description)
if form_a.is_valid() and form_b.is_valid():
form_a.save()
form_b.save()
messages.success(request, "Changes Made")
return HttpResponseRedirect(reverse('destination')
Ручное тестирование в браузере работает нормально, и все поля правильно сохраняются в базе данных.
Однако, выполнив следующий тест:
class ListingJourney(TestCase):
@classmethod
def setUpTestData(cls):
cls.client = Client()
# Create Listing
cls.listing = ...
def listing_post(self):
self.assertTrue(Listings.objects.filter(id=self.listing.id).exists())
response = self.client.get(reverse('new_listing', kwargs={'listing_id': self.listing.id}),
follow=True)
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, template_name='foo/listing.html')
response = self.client.post(reverse('new_listing', kwargs={'listing_id': self.listing.id}),
follow=True,
data={
'space_description': "Lorem ipsum dolor",
'neighborhood_description': "Lorem ipsum dolor",
'listing_instagram': "https://www.instagram.com/listing/",
'listing_facebook': "https://www.facebook.com/listing/",
# some more data
})
self.assertRedirects(response, reverse('redirect', kwargs={'listing_id': self.listing.id}),
status_code=302,
target_status_code=200,
fetch_redirect_response=True)
self.assertEqual(self.listing.listingsdescription.space_description, "Lorem ipsum dolor")
self.assertEqual(self.listing.listing_facebook, "https://www.facebook.com/listing/")
self.assertEqual(self.listing.listing_instagram, "https://www.instagram.com/listing/")
Тест не проходит при:
self.assertEqual(self.listing.listing_facebook, "https://www.facebook.com/listing/")
Traceback (most recent call last):
File "...\tests.py", line 153, in listing_post
self.assertEqual(self.listing.listing_facebook, "https://www.facebook.com/listing/")
AssertionError: None != 'https://www.facebook.com/listing/'
То есть поля Description были правильно сохранены с правильным текстом, но поля социальных сетей все еще пустые. Опять же, при ручном тестировании все работает нормально.
печать request.POST в представлении, и ручное тестирование, также показывает, что имена ключей правильные:
<QueryDict: {'csrfmiddlewaretoken': ['blabla'],
'listing_instagram': ['https://www.instagram.com/listing/'],
'listing_facebook': ['https://www.facebook.com/listing/'],
'space_description': ['Lorem ipsum dolor'],
'neighborhood_description': ['Lorem ipsum dolor']}>
Может ли быть так, что база данных каким-то образом не завершила сохранение поля модели, прежде чем утверждать, что данные сохранены правильно?
Помощь приветствуется.
Я решил эту проблему, вызвав refresh_from_db() на объекте листинга после POST-запроса.
response = self.client.post(reverse('new_listing', kwargs={'listing_id': self.listing.id}),
follow=True,
data={
'space_description': "Lorem ipsum dolor",
'neighborhood_description': "Lorem ipsum dolor",
'listing_instagram': "https://www.instagram.com/listing/",
'listing_facebook': "https://www.facebook.com/listing/",
# some more data
})
self.assertRedirects(response, reverse('redirect', kwargs={'listing_id': self.listing.id}),
status_code=302,
target_status_code=200,
fetch_redirect_response=True)
# Added this:
self.listing.refresh_from_db()
self.assertEqual(self.listing.listingsdescription.space_description, "Lorem ipsum dolor")
self.assertEqual(self.listing.listing_facebook, "https://www.facebook.com/listing/")
self.assertEqual(self.listing.listing_instagram, "https://www.instagram.com/listing/")
Я все еще не понимаю, почему тест для listing.space_description был положительным, но не для instagram & facebook. Если кто-то может объяснить, почему, это было бы здорово.