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
のはなぜですか? 何か変なことをしている場合、ブロック内のロジックをテストするにはどうすればよいでしょうか?barMock
Exception
except
ベストアンサー1
モックは例外を正常に発生させていますが、error.resp.status
値が欠落しています。 を使用するのではなく、 が属性であることをreturn_value
伝えます。Mock
status
barMock.side_effect = HttpError(mock.Mock(status=404), 'not found')
追加のキーワード引数は、Mock()
結果のオブジェクトの属性として設定されます。
私はあなたの定義をモジュールにfoo
入れて、bar
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
それは 2 番目の引数からの属性セットです。HttpError()