mock
用于单元测试中替换系统的某些部分。
Mock
和 MagicMock
是非常类似的,区别只是MagicMock
对魔法方法的改进。
此二者在访问它们的时候,会创建所有的属性和方法,并且记录下它们是如何被调用的。当然我们也可以配置他们:1.指定他们的返回值 2.限制它们哪些属性可以使用。从而可以断言他们是如何被调用的。
mock
使用了python的一个特性,即:一切皆对象,变量名指向的是某个对象的内存地址。因此,在使用mock
的时候,其实是更改了某个变量的指向。
关于mock
对象
从图中截图中可以看到mock
对象的一些属性,其中return_value
比较特殊,它的返回值默认情况下依旧是一个mock
对象。而且通过点开该mock
对象,会发现,被返回的这个mock
对象的return_value
的返回值默认依旧是一个mock
对象。。如此这般,永无止境的进行下去。当然这个return_value
是可以修改的。而且也经常会被修改。
某个方法被mock
之后,return_value
用来指定该方法被调用时的返回值。
from unittest import mock
somefunc = mock.Mock(return_value=3)
print(somefunc()) #3
somefunc_2 = mock.Mock()
somefunc_2.return_value = 3
print(somefunc_2())#3
side_effect
常用于:
- 引发错误
- 模拟列表
- 模拟字典
somefunc = mock.Mock(side_effect=KeyError())
print(somefunc())
####################
Traceback (most recent call last):
File "/home/an/PycharmProjects/daily/mock_study.py", line 11, in <module>
print(somefunc())
File "/usr/lib/python3.6/unittest/mock.py", line 939, in __call__
return _mock_self._mock_call(*args, **kwargs)
File "/usr/lib/python3.6/unittest/mock.py", line 995, in _mock_call
raise effect
KeyError
a_dict = {"a": 1, "b": 2, "c": 3}
def site(arg):
return a_dict[arg]
some_func = mock.Mock(side_effect=site)
print(some_func("a")) # 1
a_list = [1, 2, 3, 4, 5]
some_func = mock.Mock(side_effect=a_list)
print(some_func()) #1
print(some_func())#2
print(some_func()) #3
spec
可以是一个 字符串列表,或者是一个类,或者是一个对象,用来规范如何创建 mock
对象
class A(object):
def __init__(self, name, age):
self.name = name
self.age = age
def get_name(self):
return "A-{}".format(self.name)
def get_age(self):
return self.age
spec_A = mock.Mock(spec=A)
# print(spec_A.gender) # AttributeError
print(spec_A.get_name()) # <Mock name='mock.get_name()' id='140226191056736'>
spec_a = mock.Mock(spec=A('a', 10))
# print(spec_a.gender) # AttributeError
print(spec_a.age) # <Mock name='mock.age' id='140226191088272'>
spec_a.age = 99
print(spec_a.age) # 99
spec_list = mock.Mock(spec=['gender'])
# print(spec_list.name) # AttributeError
print(spec_list.gender) # <Mock name='mock.gender' id='140226191088888'>