Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/311.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何模拟外部模块调用并在类主体中测试代码_Python_Unit Testing_Python Unittest - Fatal编程技术网

Python 如何模拟外部模块调用并在类主体中测试代码

Python 如何模拟外部模块调用并在类主体中测试代码,python,unit-testing,python-unittest,Python,Unit Testing,Python Unittest,我想将静态信息存储在一个类中,由所有实例共享。信息是通过使用另一个模块获得的,我只想这样做一次,例如,假设这是我在mymodule.py中得到的: 导入操作系统 MyClass: bus=os.environ.get('DBUS\u SESSION\u bus\u ADDRESS',无) 定义初始化(自): 通过 如何测试此代码和mockos.environ.get以确保调用正确 由于执行发生在第一次导入时,我需要在测试中重新加载模块,但即使如此,我也无法在正确的时间模拟os.environ.

我想将静态信息存储在一个类中,由所有实例共享。信息是通过使用另一个模块获得的,我只想这样做一次,例如,假设这是我在
mymodule.py
中得到的:

导入操作系统
MyClass:
bus=os.environ.get('DBUS\u SESSION\u bus\u ADDRESS',无)
定义初始化(自):
通过
如何测试此代码和mock
os.environ.get
以确保调用正确

由于执行发生在第一次导入时,我需要在测试中重新加载模块,但即使如此,我也无法在正确的时间模拟
os.environ.get

导入单元测试
从unittest导入修补程序,MagicMock
导入导入库
导入mymodule
类TestMyClass(unittest.TestCase):
@补丁('mymodule.os.environ',spec=['get'])
def测试类初始补丁(自身、模拟环境):
#太早-重新加载将覆盖模拟
导入lib.reload(mymodule)
mock_env.get.assert_调用了_once_,带有('DBUS_SESSION_BUS_ADDRESS',None)
def测试类初始模拟(自):
导入lib.reload(mymodule)
#太晚了-类主体已执行
mymodule.MyClass.os.environ=MagickMock()
我已经设法提出了两个备选方案,使其可测试:

  • 将类初始化代码移动到类方法中,并从类主体调用它。我可以在单元测试中测试这个类方法

  • 将类初始化移到
    \uuuu init\uuuu
    方法中,由存储在类变量中的标志进行保护,以便在第一次实例化时仅初始化一次


虽然这两种方法都可以很好地发挥作用,但如果可能的话,将其留在课堂上会让人感觉更干净、更直接。

我已经设法找到了正确的方法(我希望)

如果您只导入了模块,而没有导入类,请将函数导入到代码的命名空间中,例如:

  • 如下所示:
    导入操作系统
  • 而不是这样:
    从操作系统导入geteuid
您可以在测试中执行此操作,直接修补
os
模块:

导入操作系统
导入单元测试
从unittest导入修补程序
导入导入库
导入mymodule
类TestMyClass(unittest.TestCase):
@修补程序('os.environ.get')
def测试类初始化补丁(自、模拟环境获取):
导入lib.reload(mymodule)
mock_env_get.assert_调用_once_,带有('DBUS_SESSION_BUS_ADDRESS',None)
官方文件中也对此进行了描述:

但是,考虑另一种情况,从导入SomeClass < /代码>而不是<代码>模块B做代码>导入< /代码>和<代码>某个函数使用<代码> A.MeCasLass<代码>。这两种导入形式都很常见。在这种情况下,我们要修补的类正在模块中查找,因此我们必须修补

a.SomeClass

通过这种方式,模块将被直接修补,重新加载您自己的模块不会影响修补

测试运行后,模块的修补将像往常一样撤消,但是请记住,类的状态与外部模块修补时初始化的状态相同,因此在运行其他测试之前,可能需要重新加载模块

确保收回“正常”类状态的最简单方法是在
TestCase
对象的
setUp
方法中重新加载模块,例如:

def设置(自):
导入lib.reload(mymodule)