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 TestCase
from . import dog
class 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
浙公网安备 33010602011771号