7

高価な機能を持つクラスがあり__init__ます。この関数をテストから呼び出したくありません。

この例では、例外を発生させるクラスを作成しました__init__

class ClassWithComplexInit(object):

    def __init__(self):
        raise Exception("COMPLEX!")

    def get_value(self):
        return 'My value'

のインスタンスを構築し、そのClassWithComplexInit関数を使用する 2 番目のクラスがあります。

class SystemUnderTest(object):

    def my_func(self):
        foo = ClassWithComplexInit()
        return foo.get_value()

の周りにいくつかの単体テストを作成しようとしていSystemUnderTest#my_func()ます。私が抱えている問題は、どのようにモックしようとしてもClassWithComplexInit__init__関数が常に実行され、例外が発生することです。

class TestCaseWithoutSetUp(unittest.TestCase):

    @mock.patch('mypackage.ClassWithComplexInit.get_value', return_value='test value')
    def test_with_patched_function(self, mockFunction):
        sut = SystemUnderTest()
        result = sut.my_func()  # fails, executes ClassWithComplexInit.__init__()
        self.assertEqual('test value', result)

    @mock.patch('mypackage.ClassWithComplexInit')
    def test_with_patched_class(self, mockClass):
        mockClass.get_value.return_value = 'test value'
        sut = SystemUnderTest()
        result = sut.my_func()  # seems to not execute ClassWithComplexInit.__init__()
        self.assertEqual('test value', result)  # still fails
        # AssertionError: 'test value' != <MagicMock name='ClassWithComplexInit().get_value()' id='4436402576'>

上記の 2 番目のアプローチは、この同様の Q&Aから得たものですが、どちらも機能しませんでした。関数を実行していないように見え__init__ましたが、結果が値ではなくモック インスタンスになるため、アサーションは失敗します。

また、ドキュメントが示唆するように関数と関数を使用してpatch、関数でインスタンスを構成しようとしました。setUpstartstop

class TestCaseWithSetUp(unittest.TestCase):

    def setUp(self):
        self.mockClass = mock.MagicMock()
        self.mockClass.get_value.return_value = 'test value'
        patcher = mock.patch('mypackage.ClassWithComplexInit', self.mockClass)
        patcher.start()
        self.addCleanup(patcher.stop)

    def test_my_func(self):
        sut = SystemUnderTest()
        result = sut.my_func()  # seems to not execute ClassWithComplexInit.__init__()
        self.assertEqual('test value', result)  # still fails
        # AssertionError: 'test value' != <MagicMock name='mock().get_value()' id='4554658128'>

__init__これも私の機能を回避しているようですが、設定した値get_value.return_valueは尊重されておらず、get_value()まだインスタンスを返していMagicMockます。

__init__テスト対象のコードによってインスタンス化された複雑なクラスをモックするにはどうすればよいですか? 理想的には、TestCase クラス内の多くの単体テストでうまく機能するソリューションが必要です (たとえば、patchすべてのテストを必要としません)。

私は Python バージョンを使用してい2.7.6ます。

4

1 に答える 1