2017-05-25 16 views
0

我正在爲Flask應用程序創建一個測試模塊。在這個Resource的get()方法中,我從Mongo獲取數據,然後遍歷它以產生輸出。我正在嘲笑集合的find()方法來返回我的迭代。問題是,在我循環遍歷迭代器的get()內,它跳過,好像它是空的。所以我試着循環測試裏面的迭代,我可以成功地看到它應該包含的3個字母。Python Mock Iterable(有點)不起作用

類屬性:

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} 

我不明白爲什麼資源正確不循環通過迭代但測試不能。任何幫助表示讚賞。

感謝

+0

我不明白你的問題。我無法重現你的問題:'x = MagicMock(); x .__ iter __。return_value = [1]'對我來說工作得很好:'for x in x:print(y)'yield'1'。請:提供一個**完整的例子,我們可以用來重現您的問題。可能還有其他的東西在創造麻煩...... – Bakuriu

+0

@Bakuriu我添加了類和設置方法。我有其他測試,但我已經評論他們,問題依然存在,所以這些都不需要。我不傳遞參數,所以search_doc()返回一個空的字典。你認爲還有什麼是相關的? – gamda

回答

0

當設定__iter__值,該行是

search.__iter__.return_value = answer 

我沒有考慮到一個事實,即filter()是調用。要達到什麼我試圖正確的做法是:

search.return_value.__iter__.return_value = answer 

因爲search模擬被被調用,一個新的MagicMock被退回,這顯然不具備__iter__屬性集。資源的get()和測試函數正在訪問不同的嘲笑,這就是爲什麼它只能在其中一個工作。

我發現的方法是通過在測試方法內部打印模擬並獲取不同的模擬ID。