151

別の関数 ( 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()

インスタンスの をクラスに設定して、モックされた関数でエラーが発生するようにする必要があると言うMock docsに従いました。side_effectMockException

他の関連する StackOverflow Q&A もいくつか調べましたが、彼らが引き起こしているのと同じことを行っているようで、モックによって例外が発生するようです。

を設定しても期待値が上がらないside_effectのはなぜですか? 何か奇妙なことをしている場合、ブロック内のロジックをテストするにはどうすればよいですか?barMockExceptionexcept

4

1 に答える 1

174

あなたのモックは問題なく例外を発生させていますが、error.resp.status値がありません。を使用するのではなく、それが属性であることをreturn_value伝えるだけです。Mockstatus

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を使いたかったと思います。いずれにせよ、それは 2 番目の引数からerror.contentの属性セットです。HttpError()

于 2015-02-03T18:07:46.517 に答える