2012-11-25 42 views
4

祝嘲笑一类具有下列要求:嘲讽类属性“autospec =真”在python

  • 类已公开的读/写性能,在其__init__()方法
  • 所定义的类具有公共属性的对象创建它是自动递增
  • 我希望用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类,使用attach_mock(),并mock_add_spec(),但总是遇上一些死胡同。

我使用标准mock库。

+1

什么嘲讽库您使用?什么是'autospec = True'? –

回答

2

由于没有答案进来的时候,我会后对我工作(不一定是最好的办法,但在这里不用):

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

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()构造为我的测试:

class TestMyClass(TestCase): 
    mock_factory = MyClassMockFactory() 

    @patch('MyClass',side_effect=mock_factory.get_mock_object) 
    test_my_class(self,*args): 
     obj0 = MyClass() 
     obj1 = MyClass(1.0,2.2) 
     obj0.calc_x_times_y() 
     # Assertions 
     obj0.calc_x_times_y.assert_called_once_with() 
     self.assertEqaul(obj0.id, 0) 
     self.assertEqaul(obj1.id, 1) 
0

对不起挖掘一个旧帖子,但是可以让你做到的东西正是你想要达到的目的是修补calc_x_times_ycalc_x_div_y并设置autospec=True那里,而不是模拟创建整个班级。

喜欢的东西:

@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