24

TestCase1つを除くすべてのテストメソッドが同じ方法でオブジェクトにパッチを適用する必要があるPythonクラスがあります。他のメソッドには、同じオブジェクトからの他の動作が必要です。私はモックを使用しているので、次のようにしました。

@mock.patch('method_to_patch', mock.Mock(return_value=1))
class Tests(TestCase):

    @mock.patch('method_to_patch', mock.Mock(return_value=2))
    def test_override(self):
         (....)

しかし、それは機能していません。がtest_override実行されると、クラスデコレータからパッチが適用された動作が呼び出されます。

多くのデバッグを行った後、TestSuiteビルド中に@patchアラウンドtest_overrideがアラウンドの前に呼び出されTestsmockパッチを順番に適用するため、クラスデコレータがメソッドデコレータをオーバーライドしていることがわかりました。

この順序は正しいですか?私は反対のことを期待していましたが、パッチを無効にする方法がよくわかりません...多分withステートメントで?

4

1 に答える 1

35

さて、ぐっすり眠り、冷たいシャワーを浴びることで、問題全体を再考することができました。私はまだモックの概念に非常に慣れていないので、それはまだ完全に正しく沈んでいません。

重要なのは、モックオブジェクトへのパッチをオーバーライドする必要がないということです。これはモックオブジェクトであり、それは私がそれを何でもできることを意味します。だから私の最初の試みは:

@mock.patch('method_to_patch', mock.Mock(return_value=1))
class Tests(TestCase):

    def test_override(self):
         method_to_patch.return_value = 2
         (....)

これは機能しましたが、以降のすべてのテストの戻り値を変更するという副作用がありました。だから私は試しました:

@mock.patch('method_to_patch', mock.Mock(return_value=1))
class Tests(TestCase):

    def test_override(self):
         method_to_patch.return_value = 2
         (....)
         method_to_patch.return_value = 1

そしてそれは魅力のように機能しました。しかし、コードが多すぎるように見えました。それで、私は次のようにコンテキスト管理の道を進みました。

@mock.patch('method_to_patch', mock.Mock(return_value=1))
class Tests(TestCase):

    def test_override(self):
         with mock.patch('method_to_patch', mock.Mock(return_value=2):
             (....)

私はそれがより明確でより簡潔に見えると思います。

patchデコレータが適用されていた順序については、実際には正しい順序です。スタックデコレータが下から上に適用されるのと同じように、メソッドデコレータはクラスデコレータの前に呼び出されることになっています。私はそれが理にかなっていると思います、私はちょうど反対の振る舞いを期待していました。

とにかく、これが将来私のような貧しい初心者の魂に役立つことを願っています。

于 2012-10-09T16:08:02.203 に答える