基于多对多关系Django模型,如何在单元测试中表示外键查找表?
Django单元测试中外键查找表(ListType)的处理方法
我来给你捋捋怎么在Django单元测试里处理这个list_type外键查找表哈~ 其实核心思路就是先预创建测试用的查找表实例,然后在后续的测试用例里直接复用这些实例来关联其他模型,下面给你一步步拆解:
第一步:先明确你的模型结构(参考)
首先得确保你的模型定义是正确的,这里先给出符合你需求的模型示例,方便后续测试代码对应:
from django.db import models from django.contrib.auth.models import User # 外键查找表:活动类型 class ListType(models.Model): name = models.CharField(max_length=50, unique=True) # 类型名称唯一 def __str__(self): return self.name # 活动项目模型 class Item(models.Model): name = models.CharField(max_length=100) type = models.ForeignKey(ListType, on_delete=models.CASCADE, related_name='items') # 可添加其他字段:event_date(活动日期)、location(地点)等 # 用户的项目列表模型 class UserList(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='lists') name = models.CharField(max_length=50) items = models.ManyToManyField(Item, related_name='lists') # 多对多关系
第二步:在测试类中预创建ListType实例
推荐在测试类的setUp方法里创建测试用的活动类型,这样每个测试方法都能直接复用,避免重复代码:
from django.test import TestCase from django.contrib.auth.models import User from .models import ListType, Item, UserList class ListAndItemTests(TestCase): def setUp(self): # 批量创建测试用的活动类型 self.movie_type = ListType.objects.create(name='电影') self.concert_type = ListType.objects.create(name='音乐会') self.sport_type = ListType.objects.create(name='体育赛事') # 顺便创建测试用户,方便测试用户列表 self.test_user = User.objects.create_user(username='jim', password='test123456')
第三步:编写具体的测试用例
接下来就可以基于预创建的ListType实例,测试各种关联场景了:
测试1:验证活动项目与ListType的外键关联正确
def test_item_has_correct_list_type(self): # 创建一个关联「电影」类型的项目 movie_item = Item.objects.create(name='流浪地球2', type=self.movie_type) # 验证外键指向正确 self.assertEqual(movie_item.type, self.movie_type) self.assertEqual(movie_item.type.name, '电影') # 验证反向关联:ListType能找到对应的项目 self.assertIn(movie_item, self.movie_type.items.all())
测试2:验证用户列表与多类型项目的关联
def test_user_list_contains_multiple_item_types(self): # 创建不同类型的活动项目 movie_item = Item.objects.create(name='满江红', type=self.movie_type) concert_item = Item.objects.create(name='五月天演唱会', type=self.concert_type) sport_item = Item.objects.create(name='NBA总决赛', type=self.sport_type) # 创建用户列表并添加项目 my_list = UserList.objects.create(user=self.test_user, name='我的必体验清单') my_list.items.add(movie_item, concert_item, sport_item) # 验证列表中项目数量正确 self.assertEqual(my_list.items.count(), 3) # 验证各类型项目的数量符合预期 self.assertEqual(my_list.items.filter(type=self.movie_type).count(), 1) self.assertEqual(my_list.items.filter(type=self.concert_type).count(), 1)
测试3:验证ListType的唯一约束
因为我们给name字段加了unique=True,所以要测试重复创建同名类型会报错:
def test_list_type_name_unique(self): # 尝试创建同名的「电影」类型,应该抛出异常 with self.assertRaises(Exception): ListType.objects.create(name='电影')
小技巧
- 如果需要创建大量测试用的ListType,可以用
bulk_create提高效率:ListType.objects.bulk_create([ ListType(name='电影'), ListType(name='音乐会'), ListType(name='体育赛事'), ListType(name='展览') ]) - 如果你有固定的测试数据,也可以用Django的fixture来加载,不过
setUp方法更灵活,适合动态调整测试数据。
内容的提问来源于stack exchange,提问作者Jim
相关产品推荐
相关产品推荐

