在模拟属性时,如何捕获单元测试中的sdk更改

时间:2013-11-13 17:41:34

标签: python unit-testing mocking

我正在为我正在开发的api客户端使用一组单元测试中的空洞mock库。我刚刚遇到API更改的问题(并且sdk上的属性被重命名)和我在测试中使用的sdk的模拟版本没有选择它(当我尝试模拟时我希望它们失败属性和方法就不存在于模拟的sdk上)。我正在重写测试以使用spec_set,但我似乎无法让它们工作。

如果我有一个具有属性MyItemClass的类name和一个方法run,我如何以这样的方式模拟它:如果在sdk中重命名属性或方法我在单元测试中拿起它。

MyItemClass就是:

class MyItemClass:
  ...

  @property
  def name(self):
    return self._details.name  

  def run(self):
    ... do something ...
    return result

目前我正在尝试:

mock_item = mock.MagicMock(spec_set=sdk.MyItemClass)
type(mock_item).name = mock.PropertyMock(return_value="Item title")       
mock_item.run = mock.MagicMock(return_value=foobar)

但是这并没有在属性MyItemClass的{​​{1}}中重新命名为name,它只是进行模拟(因此测试通过)。

同样,这段代码(由于PropertyMocks的存储方式,文档说你不应该这样做):

item_name

似乎拿起重命名(并且在设置mock_item = mock.MagicMock(spec_set=sdk.MyItemClass) mock_item.name = mock.PropertyMock(return_value="Item title") mock_item.run = mock.MagicMock(return_value=foobar) 时失败),但是当命名被修复时,模拟看起来不像以前那样工作(测试开始失败,因为属性没有返回测试期望的是什么,可能是因为name的丢弃。

1 个答案:

答案 0 :(得分:0)

这看起来像是python模拟库中的一个bug或缺少的功能。我提出了与issue相同的问题,在添加此功能之前,我的原始解决方法是最佳答案:

我使用以下代码解决它:

def add_property(mock_object, property_name, property_value) :                  
    prop = mock.PropertyMock(return_value=property_value)                       
    setattr(type(mock_object), property_name, prop)                             

    # this catches sdk changes if spec_set is used with the MagicMock as        
    # it will fail if you assign the property to an non-existant attribute                                                           
    mock_object.attach_mock(prop, property_name)

mock_item = mock.MagicMock(spec_set=sdk.MyItemClass)
add_property(mock_item, 'name', "Item title")

如果删除或重命名属性add_property,则name将在attach_mock中失败,然后根据需要中断单元测试。