2017-02-22 4 views
1

に、私は次のクラスで定義されたユニットテストmethodA、にあるとし、次のように私のテストクラスがあるどのようにユニットテストを飾っ方法

class SomeClass(object): 

    def wrapper(fun): 
     def _fun(self, *args, **kwargs): 
      self.b = 'Original' 
      fun(self, *args, **kwargs) 
     return _fun 

    @wrapper 
    def methodA(self): 
     pass 

from mock import patch 

class TestSomeClass(object): 

    def testMethodA(self): 
     def mockDecorator(f): 
      def _f(self, *args, **kwargs): 
       self.b = 'Mocked' 
       f(self, *args, **kwargs) 
      return _f 

     with patch('some_class.SomeClass.wrapper', mockDecorator): 
      from some_class import SomeClass 
      s = SomeClass() 
      s.methodA() 
      assert s.b == 'Mocked', 's.b is equal to %s' % s.b 

私がテストを実行する場合私はアサーションを打つ:

私がテストにブレークポイントを当てはめると、パッチの後に、私はを見ることができますだけで罰金を嘲笑されていますが、それmethodAはまだ古いラッパー参照:

(Pdb) p s.wrapper 
<bound method SomeClass.mockDecorator of <some_class.SomeClass object at 0x7f9ed1bf60d0>> 
(Pdb) p s.methodA 
<bound method SomeClass._fun of <some_class.SomeClass object at 0x7f9ed1bf60d0>> 

問題がここにあるものの任意のアイデアを?

答えて

0

混乱の末、私は解決策を見つけました。

猿のパッチ適用が有効であることがないようだ(と私はまたa few otherソリューションを試してみた)ので、私は、関数の内部に掘られ、それが実りあることが判明しました。

Pythonの3 あなたは幸運 - ちょうど順番に包まれた機能が含まれている__wrapped__属性を、作成wrapsデコレータを使用しています。詳細については、上記のリンク先の回答を参照してください。

Python 2 @wrapsを使用しても、ファンシー属性は作成されません。 しかし、ラッパーメソッドがクロージャーだけを行うことを理解する必要があります。そのため、ラップされた関数をfunc_closure属性で見つけることができます。

元の例では、ラップ機能がで次のようになります。のまとめs.methodA.im_func.func_closure[0].cell_contents

(HA!) 私は私のテストを容易にするために、この線に沿ってgetWrappedFunctionヘルパーを作成:

@staticmethod 
def getWrappedFunction(wrapper): 
    return wrapper.im_func.func_closure[0].cell_contents 

YMMV、とりわけあなたが空想的なことを行い、クロージャーに他のオブジェクトを含める場合は特にそうです。

関連する問題