1. ホーム
  2. python

[解決済み] Exceptionを発生させる関数をモックしてexceptブロックをテストする

2022-05-04 10:35:14

質問

ある関数( foo ) を呼び出し、別の関数 ( bar ). もし bar() が発生します。 HttpError ステータスコードが404の場合は特別に処理し、そうでない場合は再レイズするようにしたい。

私は、このようなユニットテストを書こうとしています。 foo 関数への呼び出しをモック化し bar() . 残念ながら、モック化された bar() で捕捉されるExceptionを発生させます。 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_effectMock インスタンスから Exception クラスを作成し、モック化した関数がエラーを発生させるようにします。

他のStackOverflowのQ&Aも見てみましたが、モックでExceptionを発生させるために彼らがやっていることと同じことをしているように見えます。

を設定するのはなぜですか? side_effectbarMock が発生しないので、期待した Exception が発生するのでしょうか?もし私が何か変なことをしているのなら、どのように私の except ブロックを作成することができます。

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

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

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

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

を配置しました。 foobar の定義を my_tests モジュールに追加された HttpError クラス ということで、私もそれを使って、あなたのテストを実行し、成功させることができます。

>>> 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 という属性があります。 HttpError() は、とにかく第2引数から設定します。