我使用Django的内置测试客户端为我的视图创建单元测试来创建模拟请求。 我调用的视图应该在数据库中创建一个对象。但是,当我从测试方法中查询数据库时,对象不存在 - 它既没有被创建,也没有从视图返回时被丢弃。
以下是观点:
def apply_to_cmp(request, campaign_id):
""" Creates a new Application to 'campaign_id' for request.user """
campaign = Campaign.objects.get(pk = campaign_id)
if not Application.objects\
.filter(campaign = campaign, user = request.user)\
.exists():
application = Application(**{'campaign' : campaign,
'user' : request.user})
application.save()
return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
这是一个调用它的测试:
def test_create_campaign_app(self):
""" Calls the method apply_to_cmp in .views """
c = Client()
c.login(username = self.username, password = self.password)
url = '/campaign/' + self.campaign.id + '/apply/'
response = c.get(url)
# Check whether request was successful (should return 302: redirect)
self.assertEqual(response.status_code, 302)
# Verify that an Application object was created
app_count = Application.objects\
.filter(user = self.user, campaign = self.campaign)\
.count()
self.assertEqual(app_count, 1)
这是运行测试的输出:
Traceback (most recent call last):
File "/test_views.py", line 40, in test_create_campaign_app
self.assertEqual(app_count, 1)
AssertionError: 0 != 1
方法apply_to_cmp
肯定被调用,因为response.status_code == 302
,但仍然没有创建Application对象。我做错了什么?
Client.login
失败,因为登录系统未在setUp
方法中正确初始化。我通过调用带有call_command('loaddata', 'initial_data.json')
initial_data.json
的{{1}}来修复此问题,其中包含登录系统的设置。此外,HttpResponseRedirect(request.META.get('HTTP_REFERER'))
由于显而易见的原因而无法运作。我改变了这一点
if request.META.get('HTTP_REFERER'):
return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
return HttpResponse()
因此测试
self.assertEqual(response.status_code, 200)
感谢您的帮助!
答案 0 :(得分:2)
您的代码没有什么特别突出的 - 但显然您的测试用例或您正在测试的代码并不像您想象的那样工作。现在是时候质疑你的假设了。
The method apply_to_cmp is definitely being called, since response.status_code == 302
这是您的第一个假设,可能不正确。如果检查响应对象中的其他详细信息,您可能会更好地了解正在发生的情况。例如,检查response.redirect_chain
并确认它实际上重定向到您期望的位置:
response = c.get(url, follow=True)
self.assertEqual(response.redirect_chain, [<expected output here>])
其他细节怎么样?我无法从您提供的代码中看到self.username和self.password的定义。您是否100%确定您的登录测试代码是否有效? c.login()返回&#39; True&#39;或者“假”&#39;表明登录是否成功。在我的测试用例中,我想确认登录成功。
login_success = c.login(username = self.username, password = self.password)
self.assertTrue(login_success)
你也可以更一般。如果您选中Application.objects.filter(user=self.user, campaign=self.campaign)
,则无法找到任何内容,但检查Application.objects.all()
会怎么样?您知道数据库中没有特定项目,但是您知道当时测试代码中存储在数据库中的内容(如果有的话)吗?你还期待其他物品吗?检查以确认您的期望是真的。
我认为你可以解决这个问题,但是在分析测试用例时你需要更积极一些,而不是仅仅看到你的app_count
变量不等1.检查你的响应对象,输入一些调试语句,并质疑每个假设。
答案 1 :(得分:0)
首先,如果您是django.test.TestCase
的子类,请考虑每个测试都包含在事务中的事实(official docs)。
然后,您可以将db日志记录添加到项目中,以查看是否存在对数据库的命中(official docs)。
最后请确保您在此行使用正确的查找:filter(user = self.user, campaign = self.campaign)