我不明白为什么我的测试总是失败。
我有两个模型(只显示相关代码):
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')
在我的浏览器上手动测试工作良好,并且所有字段都正确保存在数据库中。
但是,在下面运行test:
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字段被正确地保存为正确的文本,但是social media字段仍然是空的。再一次,手工测试,一切正常。
打印请求。在视图中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']}>
可能是在数据库断言数据保存正确之前,不知何故数据库还没有完成保存模型字段?
感谢您的帮助。
我通过在POST请求之后对清单对象调用refresh_from_db()来解决这个问题。
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/")
我仍然很困惑,为什么测试列表。Space_description是正面的,但instagram则不然。facebook。如果有人能解释一下原因,那就太好了。