Python单元测试:通过mock替换(或修补)函数



我读了很多关于unittest.mock的文章,但我无法将其转移到我自己的场景中。所以我在这里创建了一个最小的工作示例。

我只是在测试之前替换一个函数,并在测试结束时将其设置回原来的函数,而不使用unittest.mock问题是如何使用unittest.mock替换函数或修改返回值。

Side queston是是否有办法重置TestCases末尾隐含的mock/patch。目前它是在tearDownClass()中显式完成的。但有时我会忘记这样的事情。

#!/usr/bin/env python3
class MyData:
me = None
def __init__(self):
MyData.me = self
self.data = self._get_default_data()
def _get_default_data(self):
return "real default data"
if __name__ == '__main__':
MyData()
print(MyData.me.data)

这是测试

import unittest
from mockplay import MyData
def _test_data(self):
return "simulated test data"
class MyTest_Sim(unittest.TestCase):
@classmethod
def setUpClass(cls):
# remember the original method
cls.org_method = MyData._get_default_data
# mock the method
MyData._get_default_data = _test_data
MyData()
@classmethod
def tearDownClass(cls):
# rest the mock/patch to the origiinal
MyData._get_default_data = cls.org_method
def test_data(self):
self.assertEqual(MyData.me.data,
"simulated test data")

背景信息

实际应用程序从JSON文件中读取与用户相关的内容(例如电子邮件(。在安装后的第一次启动时,没有这样的JSON文件。因此该应用程序使用一个";"内置";默认JSON文件。每个测试以一个"0"开始;新鲜的";应用程序-文件系统上没有JSON文件。因此它使用CCD_ 5。为了控制测试中存在的数据,我需要模拟/修补/替换此方法,因为默认的JSON文件a(不适合所有测试用例,b(可能在应用程序开发过程中发生更改。

不需要替换函数。在我的示例中,只有函数的返回值才符合兴趣。

补丁在setupClass()中创建并显式启动,在tearDownClass()中显式停止。

import unittest
import unittest.mock as mock
from mockplay import MyData

class MyTest_Sim(unittest.TestCase):
@classmethod
def setUpClass(cls):
# mock the return value
cls.patcher = mock.patch('mockplay.MyData._get_default_data',
return_value='simulated test data')
# start the patch
cls.patcher.start()
# initiate data
MyData()
@classmethod
def tearDownClass(cls):
# stop the patch
cls.patcher.stop()
def test_data(self):
self.assertEqual(MyData.me.data,
"simulated test data")

Python 3.8或更新版本

在这个Python版本中,引入了新的方法addClassCleanup()。因此,您不需要在所有测试结束时小心调用patcher.stop()explicite。如果你这样做,测试类会为你做:

@classmethod
def setUpClass(cls):
# ...
# start the patch
cls.patcher.start()
# stop after all tests
cls.addClassCleanup(cls.patcher.stop)
# ...

最新更新