exceptブロックをテストするために例外を発生させる関数をモックする 質問する

exceptブロックをテストするために例外を発生させる関数をモックする 質問する

foo別の関数( ) を呼び出す関数 ( ) がありますbar。 を呼び出すとbar()が発生する場合HttpError、ステータス コードが 404 の場合は特別に処理し、それ以外の場合は再度 を発生させます。

私はこの関数の周囲にユニット テストをいくつか記述してfoo、 の呼び出しをモック化しようとしています。残念ながら、 のモック化された呼び出しで、ブロックによってキャッチされる例外を発生させるbar()ことができません。bar()except

ここに私の問題を説明するコードがあります:

import unittest
import mock
from apiclient.errors import HttpError


class FooTests(unittest.TestCase):
    @mock.patch('my_tests.bar')
    def test_foo_shouldReturnResultOfBar_whenBarSucceeds(self, barMock):
        barMock.return_value = True
        result = foo()
        self.assertTrue(result)  # passes

    @mock.patch('my_tests.bar')
    def test_foo_shouldReturnNone_whenBarRaiseHttpError404(self, barMock):
        barMock.side_effect = HttpError(mock.Mock(return_value={'status': 404}), 'not found')
        result = foo()
        self.assertIsNone(result)  # fails, test raises HttpError

    @mock.patch('my_tests.bar')
    def test_foo_shouldRaiseHttpError_whenBarRaiseHttpErrorNot404(self, barMock):
        barMock.side_effect = HttpError(mock.Mock(return_value={'status': 500}), 'error')
        with self.assertRaises(HttpError):  # passes
            foo()

def foo():
    try:
        result = bar()
        return result
    except HttpError as error:
        if error.resp.status == 404:
            print '404 - %s' % error.message
            return None
        raise

def bar():
    raise NotImplementedError()

私は模擬ドキュメントこれは、モック関数がエラーを発生させるようにするには、インスタンスside_effectのをクラスMockに設定する必要があることを示しています。Exception

また、他の関連する StackOverflow Q&A もいくつか確認しましたが、どうやら私がやっているのと同じことが原因で、モックによって例外が発生しているようです。

を設定しても、予期される が発生しないside_effectのはなぜですか? 何か変なことをしている場合、ブロック内のロジックをテストするにはどうすればよいでしょうか?barMockExceptionexcept

ベストアンサー1

モックは例外を正常に発生させていますが、error.resp.status値が欠落しています。 を使用するのではなく、 が属性であることをreturn_value伝えます。Mockstatus

barMock.side_effect = HttpError(mock.Mock(status=404), 'not found')

追加のキーワード引数は、Mock()結果のオブジェクトの属性として設定されます。

私はあなたの定義をモジュールにfoo入れて、barmy_testsHttpErrorクラス私もそれを使用でき、テストを成功させることができます:

>>> from my_tests import foo, HttpError
>>> import mock
>>> with mock.patch('my_tests.bar') as barMock:
...     barMock.side_effect = HttpError(mock.Mock(status=404), 'not found')
...     result = my_test.foo()
... 
404 - 
>>> result is None
True

行が実行中であることも確認できますprint '404 - %s' % error.messageが、代わりにそこを使用したいと考えていたと思います。いずれにせよ、error.contentそれは 2 番目の引数からの属性セットです。HttpError()

おすすめ記事