2017-10-12 67 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