在Python中使用'autospec=True'時嘲笑類屬性

2024-04-19 15:25:10 发布

您现在位置:Python中文网/ 问答频道 /正文

我想模拟一个有以下要求的班级:

  • 该类具有在其__init__()方法中定义的公共读/写属性
  • 类具有public属性,该属性在创建对象时自动递增
  • 我希望使用autospec=True,这样在调用时将严格检查类的API

简化的类示例:

class MyClass():
    id = 0

    def __init__(self, x=0.0, y=1.0):
        self.x = x
        self.y = y
        self.id = MyClass._id
        MyClass.id +=1

    def calc_x_times_y(self):
        return self.x*self.y

    def calc_x_div_y(self, raise_if_y_not_zero=True):
        try:
            return self.x/self.y
        except ZeroDivisionError:
            if raise_if_y_not_zero:
                raise ZeroDivisionError
            else:
                return float('nan')

就属性而言,我需要模拟对象的行为与原始对象相同:

  • 它应该自动增加分配给每个新创建的模拟对象的id
  • 它应该允许访问其x,y属性 但是mock方法调用应该被mock拦截,并验证其调用签名

最好的办法是什么?在

编辑

我已经尝试过几种方法,包括子类化Mock类,使用attach_mock(),和mock_add_spec(),但总是遇到一些死胡同。在

我使用的是标准的mock库。在


Tags: 对象方法selfidtruereturnif属性
2条回答

很抱歉挖出一篇旧文章,但是可以让您准确地完成您想要实现的事情的方法是修补calc_x_times_y和{}并在那里设置{},而不是嘲笑整个类的创建。在

比如:

@patch('MyClass.calc_x_times_y')
@patch('MyClass.calc_x_div_y')
test_foo(patched_div, patched_times):
my_class = MyClass() #using real class to define attributes
# ...rest of test

由于没有答案,我将发布对我有效的方法(不一定是最好的方法,但这里是这样):

我创建了一个模拟工厂,它创建了一个Mock()对象,使用描述的here语法设置其id属性,并返回该对象:

 class MyClassMockFactory():
     _id = 0

     def get_mock_object(self, *args,**kwargs):
        mock = Mock(MyClass, autospec = True)
        self._attach_mock_property(mock , 'x', kwargs['x'])
        self._attach_mock_property(mock , 'y', kwargs['y'])
        self._attach_mock_property(mock , 'id', MyClassMockFactory._id)
        MyClassMockFactory._id += 1
        return mock

     def _attach_mock_property(self, mock_object, name, value):
         p = PropertyMock(return_value=value)
         setattr(type(mock_object), name, p)

现在,我可以为我的测试修补MyClass()构造函数:

^{pr2}$

相关问题 更多 >