mock中的spec的一点用法

来源:互联网 发布:北师大网络登录 编辑:程序博客网 时间:2024/06/05 20:01

1. spec和spec_set的区别

unittest.mock in Python 3.x is basically same with mock.

According to the unittest.mock documentation:

spec: This can be either a list of strings or an existing object (a class or instance) that acts as the specification for the mock object. If you pass in an object then a list of strings is formed by calling dir on the object (excluding unsupported magic attributes and methods). Accessing any attribute not in this list will raise an AttributeError.If spec is an object (rather than a list of strings) then __class__ returns the class of the spec object. This allows mocks to pass isinstance tests.spec_set: A stricter variant of spec. If used, attempting to set or get an attribute on the mock that isn’t on the object passed as spec_set will raise an AttributeError.Update Difference between spec and spec_set.

With spec, you can set attribute that is not specified, while with spec_set, it is not allowed to set unspecified attribute.

Example:

>>> from unittest.mock import Mock>>> class A:...     def __init__(self, a, b):...         self.a = a...         self.b = b...>>> aobj = A(1, 2)>>> m = Mock(spec=aobj)   # spec>>> m.c   # get -> failTraceback (most recent call last):  File "<stdin>", line 1, in <module>  File "/usr/local/Cellar/python3/3.6.0b4_3/Frameworks/Python.framework/Versions/3.6/lib/python3.6/unittest/mock.py", line 582, in __getattr__    raise AttributeError("Mock object has no attribute %r" % name)AttributeError: Mock object has no attribute 'c'>>> m.c = 9  # set -> success>>>>>> m = Mock(spec_set=aobj)   # spec_set>>> m.a<Mock name='mock.a' id='4544967400'>>>> m.b<Mock name='mock.b' id='4545493928'>>>> m.c   # get -> failTraceback (most recent call last):  File "<stdin>", line 1, in <module>  File "/usr/local/Cellar/python3/3.6.0b4_3/Frameworks/Python.framework/Versions/3.6/lib/python3.6/unittest/mock.py", line 582, in __getattr__    raise AttributeError("Mock object has no attribute %r" % name)AttributeError: Mock object has no attribute 'c'>>> m.c = 9  # set -> failTraceback (most recent call last):  File "<stdin>", line 1, in <module>  File "/usr/local/Cellar/python3/3.6.0b4_3/Frameworks/Python.framework/Versions/3.6/lib/python3.6/unittest/mock.py", line 688, in __setattr__    raise AttributeError("Mock object has no attribute '%s'" % name)AttributeError: Mock object has no attribute 'c'

2. 一个示例

driver_mocks_spec.py

程序如下:

xxxxxCLIENT_SPEC = ('client','constants','exceptions',)xxxxxCLIENT_CONSTANTS_MOD_SPEC = (    'STATE_UNKNOWN',    'STATE_POWER_ON',    'STATE_POWER_OFF',    'STATE_POWERING_ON',    'STATE_POWERING_OFF',    'STATE_STANDBY',    'ACTION_POWER_ON',    'ACTION_POWER_OFF',    'ACTION_REBOOT',    'ACTION_POWER_CYCLE_SOFT',    'ACTION_POWER_CYCLE_GRACE')

driver_mocks.py

程序片段如下:

    xxxxx_client = importutils.try_import('xxxxx_client')if not xxxxx_client:    xxxxx_client = mock.MagicMock(spec_set=mock_specs.xxxxxCLIENT_SPEC)    sys.modules['xxxxx_client'] = xxxxx_client    sys.modules['xxxxx_client.client'] = xxxxx_client.client    xxxxx_client.constants = mock.MagicMock(        spec_set=mock_specs.xxxxxCLIENT_CONSTANTS_MOD_SPEC,        STATE_UNKNOWN="unknown",        STATE_POWER_ON="power on",        STATE_POWER_OFF="power off",        STATE_POWERING_ON="powering_on",        STATE_POWERING_OFF="powering_off",        STATE_STANDBY="standby",        ACTION_POWER_ON="powerOn",        ACTION_POWER_OFF="powerOff",        ACTION_REBOOT="powerCycleSoft",        ACTION_POWER_CYCLE_SOFT="powerCycleSoft",        ACTION_POWER_CYCLE_GRACE="powerCycleSoftGrace")    sys.modules['xxxxx_client.constants'] = xxxxx_client.constants    sys.modules['xxxxx_client.exceptions'] = xxxxx_client.exceptions    xxxxx_client.exceptions.xxxxxClientException = \        type('XClairtyClientException', (Exception,), {})if 'ironic.drivers.modules.xxxxx' in sys.modules:    six.moves.reload_module(sys.modules['ironic.drivers.modules.xxxxx'])

代码背景:
- 在pip install的xxxxx_client库中,有一个module是constants(即constants.py),它里面定义了若干变量。
- 以上代码是属于xxxxx_driver的unit test的,xxxxx_driver使用xxxxx_client库。
- 第一个spec文件,就是为mock而声明这些变量;第二个文件则是定义与使用。

参考文献:

  1. https://stackoverflow.com/questions/25323361/what-is-spec-and-spec-set/25323517#25323517
  2. https://docs.python.org/3.4/library/unittest.mock.html
  3. http://blog.csdn.net/wenph2008/article/details/46862771
原创粉丝点击