1. ホーム
  2. python

Pythonでモックを正しく使う方法(unittest setUp編

2023-08-15 11:56:54

質問

TDDを学ぶ試みで、ユニットテストとpythonのモックを使用することを学ぼうとしています。 ゆっくりとそのコツをつかんでいますが、これが正しく行われているかどうかは不明です。 予断ですが。ベンダーAPIが2.4のpycファイルとしてプリコンパイルされているので、私はpython 2.4を使うことにこだわっています。

このサンプルコードを 'mymodule.py' に記述します。

import ldap

class MyCustomException(Exception):
    pass

class MyClass:
    def __init__(self, server, user, passwd):
        self.ldap = ldap.initialize(server)
        self.user = user
        self.passwd = passwd

    def connect(self):
        try:
            self.ldap.simple_bind_s(self.user, self.passwd)
        except ldap.INVALID_CREDENTIALS:
            # do some stuff
            raise MyCustomException

ldap.initializeはldap.ldapobject.SimpleLDAPObjectを返すので、このメソッドでモックアウトしなければならないと思いました。

import unittest
from ldap import INVALID_CREDENTIALS
from mock import patch, MagicMock
from mymodule import MyClass

class LDAPConnTests(unittest.TestCase):
    @patch('ldap.initialize')
    def setUp(self, mock_obj):
        self.ldapserver = MyClass('myserver','myuser','mypass')
        self.mocked_inst = mock_obj.return_value

    def testRaisesMyCustomException(self):
        self.mocked_inst.simple_bind_s = MagicMock()
        # set our side effect to the ldap exception to raise
        self.mocked_inst.simple_bind_s.side_effect = INVALID_CREDENTIALS
        self.assertRaises(mymodule.MyCustomException, self.ldapserver.connect)

    def testMyNextTestCase(self):
        # blah blah

いくつかの質問につながります。

  1. 正しく見えますか?)
  2. これは、私がテストしているクラス内でインスタンス化されるオブジェクトをモックしようとする適切な方法でしょうか?
  3. setUpで@patchデコレーターを呼び出してもいいのでしょうか、それとも奇妙な副作用が発生するのでしょうか?
  4. テストケース・ファイルに例外をインポートすることなく、モックに ldap.INVALID_CREDENTIALS 例外を発生させる方法はありますか?
  5. 代わりに patch.object() を使用するべきですか、また、そうであれば、どのように使用しますか?

ありがとうございます。

どのように解決するのですか?

あなたは patch() を関数デコレータとしてだけでなくクラスデコレータとしても使用できます。そして、モック化した関数を先ほどと同じように渡すことができます。

@patch('mymodule.SomeClass')
class MyTest(TestCase):

    def test_one(self, MockSomeClass):
        self.assertIs(mymodule.SomeClass, MockSomeClass)

ご覧ください。 すべてのテストメソッドに同じパッチを適用する (また、代替案もリストアップされています)

すべてのテストメソッドに対してパッチを適用したい場合は、setUp でこのようにパッチャーを設定するのがより理にかなっています。