MOCK
import unittest
from unittest.mock import MagicMock
class A(unittest.TestCase):
def m1(self):
val = self.m2()
self.m3(val)
def m2(self):
pass
def m3(self, val):
pass
def test_m1(self):
a = A()
a.m2 = MagicMock(return_value="custom_val")
a.m3 = MagicMock()
a.m1()
self.assertTrue(a.m2.called) #验证m2被call过
a.m3.assert_called_with("custom_val") #验证m3被指定参数call过
if __name__ == '__main__':
unittest.main(argv=['first-arg-is-ignored'], exit=False)Mock Side Effect
可以根据不同的输入,返回不同的数值,而不只是一个 return_value。
from unittest.mock import MagicMock
def side_effect(arg):
if arg < 0:
return 1
else:
return 2
mock = MagicMock()
mock.side_effect = side_effect
mock(-1)
1
mock(1)
2Patch
可以应用 Python 的 decoration 模式或是 context manager 概念,快速自然地 mock 所需的函数。
from unittest.mock import patch
@patch('sort')
def test_sort(self, mock_sort):
...
...在这个 test 里面,mock_sort 替代 sort 函数本身的存在,所以,可以像开始提到的 mock object 一样,设置 return_value 和 side_effect。
另一种 patch 的常见用法,是 mock 类的成员函数,比如说一个类的构造函数非常复杂,而测试其中一个成员函数并不依赖所有初始化的 object。它的用法如下:
with patch.object(A, '__init__', lambda x: None):
…代码应该也比较好懂。在 with 语句里面,通过 patch,将 A 类的构造函数 mock 为一个 do nothing 的函数,这样就可以很方便地避免一些复杂的初始化(initialization)。