Python 标准库 unittest 不同遮掩方式的比较
背景
最近在搞 TDD , 有些 mock 的写法怕后面忘记了,在这里记录下现在针对 unittest 的一些心得。
目前针对 unittest 的 mock 最佳实践
假设我们有一个 dog.py 的代码,它的内容如下
class Dog(object):def get_name(self):return "dog"def fun():return "123"
那么它同级目标下 test_dog.py 这样写看起来比较好
from unittest.mock import MagicMock, patch
from unittest import TestCasefrom . import dogclass TestDogTestCase(TestCase):def test_dog_a(self):"""方法一:直接使用 patch 来遮掩目标方法,它有一个问题如果后面我们的文件名变了,路径变了都要调整这个字符串非常不方便。"""mock_get_name = MagicMock()mock_get_name.return_value = "hello"with patch("utils.dog.Dog.get_name", mock_get_name):d = dog.Dog()assert d.get_name() == "hello"def test_dog_b(self):"""方法二:使用 patch.object 来遮掩目标方法,这样字符串就只包括方法名了,对于源文件目标的变更就不影响测试用例了,所以这个相对友好一些。"""mock_get_name = MagicMock()mock_get_name.return_value = "hello"with patch.object(dog.Dog, "get_name", mock_get_name):d = dog.Dog()assert d.get_name() == "hello"def test_dog_c(self):"""方法三:把模块也看成对象,这位模块内的函数也就成方法了, 这个就能都统一到 patch.object 一个来解决了,感觉比较友好。"""mock_get_name = MagicMock()mock_get_name.return_value = "hello"with patch.object(dog, "fun", mock_get_name):assert dog.fun() == "hello"assert mock_get_name.called == True
