我正在为Flask应用程序创建一个测试模块。在这个Resource
的get()方法中,我从Mongo获取数据,然后遍历它以产生输出。我正在嘲笑集合的find()
方法来返回我的迭代。问题是在我遍历迭代的get()
内部,它跳过就像是空的一样。所以我尝试在测试中循环遍历迭代,我可以成功地看到它应该包含的3个词。
类属性:
class _TestAll(BaseAllReports):
collection = MagicMock()
bool_columns = ('bool1', 'bool2')
string_set_columns = ('string1', 'string2')
int_columns = ('int1', 'int2')
text_columns = ('text1', 'text2')
stats_columns = ('bool1', 'int1')
Resource.get():
def get(self):
args = self.parser().parse_args()
search = self.search_doc(args)
docs = self.collection.find(search, {'_id': False})
print(docs)
ids, total_hurt, total_dead = set(), 0, 0
stats = dict((x, {}) for x in self.stats_columns)
stats['month'] = {}
for d in docs:
print('get', d)
if d['id'] in ids:
continue
else:
ids.add(d['id'])
for s in self.stats_columns:
if s in self.bool_columns:
key = u'Sí' if d[s] else 'No'
else:
key = d[s]
number = stats[s].get(key, 0) + 1
stats[s][key] = number
month_key = d['timestamp'].strftime('%b')
month_summary = stats['month'].get(month_key, {'hurt': 0, 'dead': 0})
month_summary['hurt'] += d['total_hurt']
month_summary['dead'] += d['total_dead']
stats['month'][month_key] = month_summary
total_hurt += d['total_hurt']
total_dead += d['total_dead']
return {
'incidents': len(ids),
'involved': docs.count(),
'affected': total_hurt + total_dead,
'hurt': total_hurt,
'dead': total_dead,
'stats': stats
}
测试设置:
@classmethod
def setUpClass(cls):
app.testing = True
cls.app = app.test_client()
cls.url = '/incidents'
cls.url_with_key = '/incidents?key=testKeyHash'
api.add_resource(_TestAll, cls.url)
测试:
def test_get(self):
with patch('__main__._TestAll.collection.find') as search:
answer = []
for i in range(3):
answer.append({
'id': i,
'bool1': True, 'bool2': False,
'string1': 'test', 'string2': 'test',
'int1': 1, 'int2': 2,
'text1': 'test', 'text2': 'test',
'timestamp': datetime.now(), 'total_hurt': 1, 'total_dead': 0})
search.__iter__.return_value = answer
search.return_value.count.return_value = len(answer)
response = self.app.get(self.url_with_key)
data = json.loads(response.data.decode())
for i in search:
print('test', i)
print(data)
self.assertEqual(_TestAll.collection.find.call_count, 1)
self.assertIn('stats', data)
for s in _TestAll.stats_columns:
self.assertIn(s, data['stats'])
终端输出:
<MagicMock name='find()' id='4423760080'>
('test', {'timestamp': datetime.datetime(2017, 5, 25, 13, 3, 9, 255912), 'text2': 'test', 'text1': 'test', 'int1': 1, 'int2': 2, 'id': 0, 'bool1': True, 'bool2': False, 'total_hurt': 1, 'total_dead': 0, 'string2': 'test', 'string1': 'test'})
('test', {'timestamp': datetime.datetime(2017, 5, 25, 13, 3, 9, 255923), 'text2': 'test', 'text1': 'test', 'int1': 1, 'int2': 2, 'id': 1, 'bool1': True, 'bool2': False, 'total_hurt': 1, 'total_dead': 0, 'string2': 'test', 'string1': 'test'})
('test', {'timestamp': datetime.datetime(2017, 5, 25, 13, 3, 9, 255928), 'text2': 'test', 'text1': 'test', 'int1': 1, 'int2': 2, 'id': 2, 'bool1': True, 'bool2': False, 'total_hurt': 1, 'total_dead': 0, 'string2': 'test', 'string1': 'test'})
{u'stats': {u'bool1': {}, u'int1': {}, u'month': {}}, u'involved': 3, u'dead': 0, u'hurt': 0, u'incidents': 0, u'affected': 0}
我不明白为什么Resource没有通过iterable正确循环但测试不能。任何帮助表示赞赏。
由于
答案 0 :(得分:1)
设置__iter__
值时,该行
search.__iter__.return_value = answer
我没有考虑到filter()
可以调用的事实。实现我的目标的正确方法是:
search.return_value.__iter__.return_value = answer
因为正在调用search
模拟,所以返回了一个新的MagicMock
,显然没有设置__iter__
属性。资源的get()
和测试函数正在访问不同的模拟,这就是为什么它只能在其中一个上工作。
我发现的方法是在测试方法中打印模拟并为其获取不同的模拟ID。