Python unittest:如何在测试方法内设置mock的side_effect返回不同值
解决方法:在测试方法内部设置mock的side_effect
我来帮你搞定这个问题!你之前的代码之所以没得到预期的Order实例,是因为把side_effect的位置放错了——你给mock_qs.return_value的MagicMock设置了side_effect,但实际上被patch的filter方法本身才是需要设置side_effect的对象。
正确的测试代码写法
from unittest import mock, TestCase from your_app.models import Order # 替换成你的Order模型实际路径 def method_to_test(): qs1 = Order.objects.filter() qs2 = Order.objects.filter() return qs1, qs2 # 方便测试验证返回结果 class TestOrderFilterMethod(TestCase): @mock.patch('your_app.models.Order.objects.filter') # 注意patch路径要与实际调用路径匹配 def test_method_to_test(self, mock_filter): # 直接在测试方法内部给被patch的filter方法设置side_effect mock_filter.side_effect = [Order(id=1), Order(id=2)] # 调用待测试方法 result1, result2 = method_to_test() # 验证结果符合预期 self.assertEqual(result1.id, 1) self.assertEqual(result2.id, 2) # 额外验证filter方法被调用了两次 self.assertEqual(mock_filter.call_count, 2)
关键说明
- 理清mock对象层级:
mock_filter就是被patch后的Order.objects.filter方法本身,当你调用Order.objects.filter()时,本质是调用这个mock对象。所以直接给它设置side_effect属性,就能让每次调用返回不同的值。 - side_effect的作用:当给mock对象设置
side_effect为一个列表时,每次调用mock对象会依次返回列表中的元素,正好满足你两次查询返回不同结果的需求。 - 无需装饰器提前配置:完全不需要在
@mock.patch里指定side_effect参数,在测试方法内部拿到mock参数后直接赋值即可,完美符合你的需求。
如果你的场景中filter应该返回QuerySet而不是单个实例,只需要把side_effect的元素改成QuerySet格式就行,比如:
mock_filter.side_effect = [ Order.objects.filter(id=1), # 可根据实际情况用真实QuerySet或模拟的QuerySet Order.objects.filter(id=2) ]
内容的提问来源于stack exchange,提问作者jalanga
相关产品推荐
相关产品推荐

