类型错误:'NoneType'对象在 Django 消息单元测试中不可下标



我正试图对一个视图进行单元测试,当数据库中的某些输入重复时,该视图会返回消息。这会给我错误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,这意味着没有给定上下文。为什么在这里使用重定向!?

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

然而,关于测试的文档[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]), 'رقم الهاتف مستخدم من قبل')

最新更新