Django中允许为空的表单字段如何编写单元测试
问题解决方案
核心错误原因
你当前测试代码直接使用self.company.__dict__作为POST提交参数,混淆了模型层属性规则和表单提交数据规则:HTTP POST表单不存在None类型,空值对应空字符串,文件字段单独走文件流传输通道,所以直接传递模型实例属性会触发各类类型错误。
各场景处理方法
1. 数值型可空字段(如street_num)留空
POST提交时传空字符串''即可,Django的ModelForm会自动将合法的空输入转换为None存入数据库,不需要你手动给模型字段赋值''。
2. 字符型可空字段(如street_cplt)留空
POST提交时直接传空字符串''即可,符合表单校验规则。
3. 文件型可空字段(如logo)留空
POST参数中直接不携带该字段的键即可,如果需要传文件则放到client.post的files参数中,不要放在普通POST数据里。
修改后的测试代码示例
def create_dummy_company(name): return Company.objects.create( company_name=name, comp_slug=slugify(name), logo=SimpleUploadedFile(name='logo.jpg', content=b'content', content_type='image/jpeg'), street_num=1, street_cplt='测试补充地址', address='dummy address' ) class TestOptions(TestCase): def test_adm_options_update_nullable_fields(self): self.company = create_dummy_company("Test company") url = reverse("polls:adm_options", args=[self.company.comp_slug]) response = self.client.get(url) self.assertEqual(response.status_code, 200) # 手动构造符合表单规则的POST参数,不要直接用模型的__dict__ post_data = { "company_name": self.company.company_name, "comp_slug": self.company.comp_slug, "address": "new address", # 可空字段留空 "street_num": "", "street_cplt": "", # logo字段直接不写,代表留空 } response = self.client.post(url, post_data) self.company.refresh_from_db() self.assertEqual(response.status_code, 200) # 验证核心字段更新成功 self.assertEqual(self.company.address, "new address") # 验证可空字段已正确设为空 self.assertIsNone(self.company.street_num) self.assertEqual(self.company.street_cplt, "") self.assertFalse(self.company.logo)
额外优化建议
如果你需要测试保留原有logo不修改的场景,可以继续在POST参数中不携带logo字段,表单会默认保留实例原有值,不会清空。如果需要测试更新logo的场景,按如下方式提交即可:
post_data = { # 其他字段同上 } files = { "logo": SimpleUploadedFile(name='new_logo.jpg', content=b'new_content', content_type='image/jpeg') } response = self.client.post(url, post_data, files=files)
内容的提问来源于stack exchange,提问作者Christophe
相关产品推荐
相关产品推荐

