2017-10-12 69 views
3

導入的方法內進口我得到了以下功能測試:如何嘲笑一個功能,即從不同的模塊

my_package.db_engine.db_functions.py:

from ..utils import execute_cmd 
from my_package.db_engine.db_functions import dbinfo 

def dbinfo(db_name): 
    params = (cmd_cfg.DB, add_pj_suffix(db_name)) 
    cmd = get_db_cmd_string(cmd_cfg.DBINFO, params=params) 
    cmd_result = execute_cmd(cmd) 
    result_dict = map_cmd_output_to_dict(cmd_result) 
    return result_dict 

此功能獲取數據庫的名稱,然後從中建立一個命令字符串並使用execute_cmd方法執行該命令爲subprocess。 我想測試這個功能,而不需要實際執行subprocess。我只想檢查命令是否已正確構建並正確傳遞至execute_cmd。因此我需要模擬從模塊utils導入的execute_cmd方法。

我的文件夾結構如下:

my_project 
|_src 
| |_my_package 
| | |_db_engine 
| | | |_db_functions.py 
| | | |_ __init__.py 
| | |_utils.py 
| | |_ __init__.py 
| | |_ .... 
| |_ __init__.py 
|_tests 
    |_test_db_engine.py 

所以對於我的測試,我試過在test_db_engine.py如下:

import unittest 
from mock import patch 

from my_pacakge.db_engine.db_functions import dbinfo 


def execute_db_info_cmd_mock(): 
    return { 
      'Last Checkpoint': '1.7', 
      'Last Checkpoint Date': 'May 20, 2015 10:07:41 AM' 
    } 


class DBEngineTestSuite(unittest.TestCase): 
    """ Tests für DB Engine""" 

    @patch('my_package.utils.execute_cmd') 
    def test_dbinfo(self, test_patch): 
     test_patch.return_value = execute_db_info_cmd_mock() 
     db_info = dbinfo('MyDBNameHere') 
     self.assertEqual(sandbox_info['Last Checkpoint'], '1.7') 

實際產量命令爲1.6Last Checkpoint的執行。因此,爲了驗證是否使用了模擬返回值,我將其設置爲1.7。 但是沒有使用該函數的模擬,因爲測試用例的執行仍然產生1.6,因爲它正在執行本應該用模擬進行修補的實際函數。

任何想法我在這裏錯了什麼?

回答

3

您正在修補錯誤的位置。從Where to patch section

patch()作品(暫時)改變對象的名稱指向與另一之一。可以有許多名稱指向任何單個對象,因此爲了修補工作,您必須確保您修補被測系統使用的名稱。

基本原理是你修補對象的位置擡頭,它不一定與它定義的位置相同。

你的代碼下測試發現execute_cmd在自己的模塊一個全球性的,但你沒有打補丁參考:

from ..utils import execute_cmd 

my_package.utils.execute_cmd參考修補,但在my_package.db_engine.db_functionsexecute_cmd參考仍然會指向原始的未修補功能。

補丁進口,而不是全球:

@patch('my_package.db_engine.db_functions.execute_cmd') 

現在execute_cmd查找內部dbinfo將使用補丁的模仿對象,而不是原來的世界由from ... import ...聲明的約束。

+0

謝謝,這個工作正常=) – Igle