我正在编写一些单元测试,并希望使用Mock。
给出以下代码:
# the 'real' query set is a Django database model
# qs = SomeDjangoModel.objects.filter(name='some_name')
qs = mock.Mock()
qs.filter.return_value = qs
item = mock.Mock()
item.do_work.return_value = "Some text"
qs.iter.return_value = iter([item])
# below is the code I want to test..
qs = qs.filter(name='some name')
qs = qs.filter(valid_from__lte=Timezone.now())
for obj in qs:
obj.do_work()
跑步时,我得到了
TypeError:'模拟'对象不可迭代
我尝试过修补
@mock.patch('__builtin__.iter')
但我似乎无法让它发挥作用。 我还没有成功地弄清楚当for循环查询设置“使用”时真正发生了什么。
非常感谢帮助!
[使用进一步添加的示例代码编辑,在第一个解决方案提案后]
答案 0 :(得分:2)
您必须使用已定义__iter__
的{{3}}和iterator
from unittest.mock import Mock, MagicMock
from datetime import datetime
qs = MagicMock()
qs.filter.return_value = qs
item = Mock()
item.do_work.return_value = "Some text"
qs.iterator.return_value = iter([item])
# below is the code I want to test..
qs = qs.filter(name='some name')
qs = qs.filter(valid_from__lte=datetime.now())
for obj in qs:
obj.do_work()
答案 1 :(得分:1)
通常我将QuerySet模拟为一个列表,这似乎更容易。所以:
something.return_value = [item]
其中something
是您计算QuerySet的函数或位置。作为一个实际的例子:
MyModel.objects.filter.return_value = [item]
这仅适用于您未使用QuerySet特定特征的情况。
答案 2 :(得分:1)
我的一位同事帮我解决了这个问题。我想要以下代码。
def the_iter(self):
return iter(self.my_test_list)
def test_my_code(self):
qs = mock.Mock()
qs.filter.return_value = qs
the_item = mock.Mock()
the_item.do_work.return_value = "Some text"
self.my_test_list = [the_item]
qs.__iter__ = mock.Mock(side_effect=self.the_iter)
# below is the code I want to test..
qs = qs.filter(name='some name')
qs = qs.filter(colour='Yellow')
for obj in qs:
print obj.do_work()