TypeError:“ NoneType”对象在消息的Django单元测试中无法下标

时间:2019-01-14 13:46:54

标签: django unit-testing

我正在尝试对视图进行单元测试,以便在数据库中重复某些输入时返回一条消息。它给我错误TypeError: 'NoneType' object is not subscriptable

这是视图

@login_required
def worker_create(request):
    worker_create_form = WorkerCreateForm(request.POST)
    if request.method == 'POST':
        if worker_create_form.is_valid():
            form = worker_create_form.save(commit=False)
            phone = form.phone
            check_phone = Worker.objects.filter(phone=phone)
            if check_phone.count() != 0:
                messages.error(request, 'رقم الهاتف مستخدم من قبل')
            else:
                form.save()
                return redirect('worker_list')
    else:
        worker_create_form = WorkerCreateForm(request.POST)
    context = {
        'worker_create_form': worker_create_form,
    }
    return render(request, 'erp_system/worker/create.html', context)

这是我为此创建的测试

class WorkerCreateTest(TestCase):
    def setUp(self):
        User.objects.create_user(username='test_user', email='test@gmail.com', password='test_password')
        branch = Branch.objects.create(name='test branch')
        Worker.objects.create(name="ay btngan ", phone='01207199086', branch=branch)

    def test_get_request_unauthenticated(self):
        response = self.client.get(reverse('worker_create'))
        url = reverse('worker_create')
        self.assertRedirects(response, '/login/?next=' + url)

    def test_get_request_authenticated(self):
        self.client.login(username='test_user', password='test_password')
        response = self.client.get(reverse('worker_create'))
        self.assertEqual(response.status_code, 200)
        self.assertTemplateUsed('erp_system/worker/create.html')

    def test_post_request_empty_data(self):
        self.client.login(username='test_user', password='test_password')
        response = self.client.post(reverse('worker_create'), {})
        self.assertFormError(response, 'worker_create_form', 'name', 'This field is required.')
        self.assertFormError(response, 'worker_create_form', 'phone', 'This field is required.')
        self.assertFormError(response, 'worker_create_form', 'branch', 'This field is required.')

    def test_post_request_invalid_data(self):
        self.client.login(username='test_user', password='test_password')
        branch = Branch.objects.create(name='test again ')
        name = 'just a name'
        for i in range(300):
            name += 'h'
        response = self.client.post(reverse('worker_create'),
                                    {'name': name, 'phone': '01207199086', 'branch': branch.id})
        self.assertEqual(response.status_code, 200)

    def test_post_request_duplicated_phone(self):
        self.client.login(username='test_user', password='test_password')
        branch = Branch.objects.create(name='test again ')
        response = self.client.post(reverse('worker_create'),
                                    {'name': 'test worker', 'phone': '01207199086', 'branch': branch.id})
        print(response)
        messages = list(response.context['messages'])
        self.assertEqual(len(messages), 1)
        self.assertEqual(str(messages[0]), 'رقم الهاتف مستخدم من قبل')

    def test_post_request_valid_data(self):
        self.client.login(username='test_user', password='test_password')
        branch = Branch.objects.create(name='test branch1234')
        name = 'new valid name'
        response = self.client.post(reverse('worker_create'),
                                    {'name': name, 'branch': branch.id, 'phone': '0151951115'})
        self.assertEqual(response.status_code, 302)

重要 当我添加print(response)时,我注意到它不仅给我HttpResponseRedirect,而且还给了我HttpResponse,这意味着没有上下文。为什么在这里使用重定向!?

1 个答案:

答案 0 :(得分:1)

在测试test_post_request_duplicated_phone中,您向worker_create发出POST请求,并且由于存在已存在给定phone的记录,因此希望检索错误。

documentation on tests [Django-doc]却提到:

  

另一方面,TestCase不会在测试后截断表。而是将测试代码封装在数据库事务中,该数据库事务在测试结束时回滚。这样可以保证测试结束时的回滚将数据库恢复到其初始状态

因此,这意味着,除非实施一些“技巧”以防止这种情况发生,否则在您输入第二项测试时,一项测试(在数据库上)所产生的副作用将消失。这是有道理的,因为重新排序测试不会导致不同的结果。

不过,您可以预先在测试中创建此类Worker对象,从而确保测试确实会出错:

def test_post_request_duplicated_phone(self):
    self.client.login(username='test_user', password='test_password')
    branch = Branch.objects.create(name='test again ')
    Worker.objects.create(name=" just a name ", phone='01207199086', branch=branch)
    response = self.client.post(reverse('worker_create'),
                                {'name': 'test worker', 'phone': '01207199086', 'branch': branch.id})
    print(response)
    messages = list(response.context['messages'])
    self.assertEqual(len(messages), 1)
    self.assertEqual(str(messages[0]), 'رقم الهاتف مستخدم من قبل')