2017-01-11 52 views
1

我是python mock中的新手,最近我試圖爲我的函數編寫測試代碼。 該函數用於分析Mongo數據庫和CSV報告。我想修補「get_collection()」函數。該結構是這樣的:模擬補丁函數

mongo_report.py文件:

import pymongo 

def get_collection(): # used to get mongo collection 

def from_report(): #used to from a report 
    get_collection(mongodb, mongo_collection_name) 
    ..... 

在我的測試文件:

from mongo_report import from_report 
from mock import Mock, patch 

def mock_get_collection(): # used to replace get_collection() 
    mocked_collection = Mock() 
    mock_get_collection.count.side_effect = [20, 6, 2] 
    mock_get_collection.find.side_effect = [{user: xx}] 
    return mocked_collection 

@patch('mongo_report.get_collection') 
def mongo_report_test(mock_call): 
    mock_call.return_value = mock_get_collection() 
    from_report() 

補丁是由什麼我在網頁上了解到書面https://blog.fugue.co/2016-02-11-python-mocking-101.html
但沒有工作。所以我的問題是:

  1. 這是使用補丁的正確方法,如果不是,我該如何補丁?

  2. 在mongo_report_test(mock_call),哪裏是mock_call從何而來,它不掛任何東西在這裏,我怎麼可以聲明其

  3. 補丁後,我怎麼能叫這個測試功能?

從裝飾師開始學習,花了整整一天,我的頭撞到桌子上,但仍然沒有學到這個把戲。 :<

+0

這看起來像一個有點迂迴的方式做到這一點,但它看上去是可行的我。 (你在'mock_get_collection'中使用'side_effect'看起來有點可疑,否則......)你能更清楚地解釋一下你的意思是「它沒有工作」嗎? – mgilson

+0

我想我的意思是我不知道如何打補丁後給他們打電話。當我調用mongo_report_test時,我需要傳遞「mock_call」參數,對吧,但是真正的mock_call是什麼?我不明白。它是另一個「mock_call = Mock()」嗎? –

回答

1

我花了一段時間才能弄清楚,原來答案是誤導。這是一個與您的問題非常相似的工作副本,我唯一不知道的是get_connection()的返回值。蟒蛇v2.6.6

#/usr/bin/env pthon 
    import unittest 
    import mock 
    from mock import MagicMock 

    class Mongo(object): 
     def __init__(self, *args, **kwargs): 
      # doing nothing for demo 
      pass 

     def get_collection(self, input1): 
      # return fixed list for demo 
      return [1, 3, 5] 

     def from_report(self, input_a, input_b): 
      collection_a = self.get_collection(input_a) 
      collection_b = self.get_collection(input_b) 
      return collection_a + collection_b 

    class TestMongo(unittest.TestCase): 

     def setUp(self): 
      self.expected = [2, 4, 6, 2, 4, 6] 
      self.mock_value = [2, 4, 6] 

     def tearDown(self): 
      pass 

     """ in the format of file_name.class_name.method_name 
     @mock.patch('test_mongo.Mongo.get_collection') 
     def test_using_mock_patch(self, mock_get_collection): 
      mock_get_collection.return_value = self.mock_value 
      mongo = Mongo() 
      mongo.get_collection = mock_get_collection 
      result = mongo.from_report('any', 'where') 
      self.assertEquals(result, self.expected) 

     """ mock.MagicMock 
     def test_mongo_get_collection_using_magicMock(self): 
      mock_mongo = MagicMock(name='get_collection') 
      mock_mongo.get_collection.return_value = self.mock_value 
      mongo = Mongo() 
      mongo.get_collection = mock_mongo.get_collection 
      result = mongo.from_report('any', 'where') 
      self.assertEquals(result, self.expected) 

     """ mock.Mock 
     def test_mongo_get_collection_using_Mock(self): 
      mock_mongo = mock.Mock(name='get_collection') 
      mock_mongo.get_collection.return_value = self.mock_value 
      mongo = Mongo() 
      mongo.get_collection = mock_mongo.get_collection 
      result = mongo.from_report('any', 'where') 
      self.assertEquals(result, self.expected) 


    if __name__ == '__main__': 
     suite = unittest.TestLoader().loadTestsFromTestCase(TestMongo) 
     unittest.TextTestRunner(verbosity=2).run(suite) 

這裏是命令和輸出

-bash-4.1$ python test_mongo.py 
    test_mongo_get_collection_using_Mock (__main__.TestMongo) ... ok 
    test_mongo_get_collection_using_magicMock (__main__.TestMongo) ... ok 
    test_using_mock_patch (__main__.TestMongo) ... ok 

    ---------------------------------------------------------------------- 
    Ran 3 tests in 0.005s 

    OK 
    -bash-4.1$ nosetests -vv test_mongo.py 
+0

我想第二個解決方案看起來正是我所需要的。謝謝!我得到的另一個問題是我怎麼稱呼它?如果我調用test_from_report,我缺少一個我需要傳遞的參數,對吧? 「mock_get_collection」一個? –

+0

@Robinsonwei,這是不容易解釋的模擬,以前的代碼不工作後,我測試,這應該工作。 – Gang

0

除非這是一些切正粘貼錯誤,我相信這一點:

mock.count.side_effect = [20, 6, 2] 
mock.find.side_effect = [{user: xx}] 

應該是:

mocked_collection.count.side_effect = [20, 6, 2] 
mocked_collection.find.side_effect = [{user: xx}] 
+0

是的,很抱歉,這是一個錯誤的粘貼錯誤 –