2012-11-25 48 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