Python Mock:如何允许字典属性取指定列表中的特定值?
实现字典属性的枚举值断言方案
我来给你几个实用的办法,帮你实现这个需求——确保测试中的city字段只能取指定的两个值,同时还能复用那个被大量用例依赖的共享常量字典:
方法一:直接拆分断言(简单直接)
既然共享常量里的city只是占位,我们可以在测试里单独对city做范围断言,其他固定字段直接用相等断言:
def test_something(self): result = something.query("something") actual_geoip = result[0]["data"]["geoip"] # 先验证固定值字段(比如country) self.assertEqual(actual_geoip["country"], expected_geoip["country"]) # 单独验证city必须是指定值之一 self.assertIn(actual_geoip["city"], ["Helsinki", "Espoo"], msg=f"City 只能是 Helsinki 或 Espoo,实际得到: {actual_geoip['city']}")
这种方式的好处是不需要修改共享常量,不会影响其他依赖这个常量的测试用例,代码也直观易懂,适合字段规则简单的场景。
方法二:优化常量定义+自定义断言函数(维护友好)
如果想把city的允许值规则也统一放在常量文件里,方便后续维护,可以修改常量的结构,再写个通用的断言函数:
第一步:修改共享常量文件
expected_geoip = { "country": "Finland", # 把city改成存储允许值的结构 "city": {"allowed_values": ["Helsinki", "Espoo"]} }
第二步:写通用断言函数(可以放在测试基类或辅助模块)
def assert_geoip_valid(self, actual_geoip): # 验证固定值字段 self.assertEqual(actual_geoip["country"], expected_geoip["country"]) # 验证city的取值范围 allowed_cities = expected_geoip["city"]["allowed_values"] self.assertIn(actual_geoip["city"], allowed_cities, msg=f"City 必须是 {allowed_cities} 之一,实际得到: {actual_geoip['city']}")
第三步:在测试用例中调用
def test_something(self): result = something.query("something") actual_geoip = result[0]["data"]["geoip"] self.assert_geoip_valid(actual_geoip)
这种方式的优势是规则集中管理,所有测试用例都用同一个断言函数,后续如果要修改允许的城市列表,只需要改常量文件就行,不用逐个修改测试用例。
方法三:用subTest做批量字段验证(扩展性强)
如果后续有更多字段需要类似的枚举值规则,可以用unittest的subTest来批量验证,这样一次就能找出所有不符合规则的字段:
def test_something(self): result = something.query("something") actual_geoip = result[0]["data"]["geoip"] # 定义所有字段的验证规则:固定值用字符串,枚举值用列表 field_validation_rules = { "country": expected_geoip["country"], "city": ["Helsinki", "Espoo"] } for field, rule in field_validation_rules.items(): with self.subTest(field=field): if isinstance(rule, list): # 枚举值规则:断言实际值在列表中 self.assertIn(actual_geoip[field], rule) else: # 固定值规则:断言相等 self.assertEqual(actual_geoip[field], rule)
这种方式的好处是扩展性极佳,新增字段规则只需要在field_validation_rules里加一行就行,而且subTest会把所有不匹配的字段都报告出来,不用反复运行测试排查问题。
内容的提问来源于stack exchange,提问作者Juha Untinen




