Skip to main content
 首页 » 编程设计

python之Django 测试客户端不创建数据库条目

2024年11月01日20tuyile006

我正在使用 Django 的内置测试客户端创建模拟请求来为我的 View 创建单元测试。 我正在调用的 View 应该在数据库中创建一个对象。但是,当我从测试方法中查询数据库时,对象不存在 - 它要么尚未创建,要么在从 View 返回时已被丢弃。

这是 View :

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 对象。我做错了什么?

请您参考如下方法:

您的代码没有特别突出的问题 - 但显然您的测试用例或您正在测试的代码没有按照您的想法工作。现在是质疑您的假设的时候了。

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() 返回“True”或“False”以指示登录是否成功。在我的测试用例中,我喜欢确认登录是否成功。

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 . 检查您的响应对象,放入一些调试语句,并质疑每个假设。