私はaiohttpを使って簡単なHTTPクライアントを作成しましたが、aiohttp.ClientSession
とaiohttp.ClientResponse
にパッチを当ててテストしようとしています。しかし、あたかもunittest.mock.patch
デコレータが私の非同期コードを尊重していないかのように見えます。推測すると、私はそれが何らかの名前空間の不一致であると言います。ここでunittest.mock.patchでaiohttpクライアントをテストする
は、最小限の例です:
from aiohttp import ClientSession
async def is_ok(url:str) -> bool:
async with ClientSession() as session:
async with session.request("GET", url) as response:
return (response.status == 200)
this answerで説明したように、私は、テストのための非同期デコレータを使用しています。だからここに私が試みテストだ:それは__main__
、たとえば、中に使われていたときに
import unittest
from unittest.mock import MagicMock, patch
from aiohttp import ClientResponse
from my.original.module import is_ok
class TestClient(unittest.TestCase):
@async_test
@patch("my.original.module.ClientSession", spec=True)
async def test_client(self, mock_client):
mock_response = MagicMock(spec=ClientResponse)
mock_response.status = 200
async def _mock_request(*args, **kwargs):
return mock_response
mock_client.request = mock_response
status = await is_ok("foo")
self.assertTrue(status)
私is_ok
コルーチンが正常に動作しますが、私は、テストを実行すると、それは私にsession.request
機能があたりに嘲笑されていないことを示すエラーを与えます私のpatch
コール。 (具体的には、「が偽装されていないと、「foo」からホスト名を解析できませんでした」というメッセージが表示されます)
私はこの動作をエスケープできません。私は試しました:
is_ok
を読み込んだ後に試しました。 、mock_client
とmock_client.__aenter__
にモックを割り当てるMagicMock(return_value=mock_response)
からmock_client.request
を設定、またはmock_client().request
を用いる- 様々な組合せなど
- 特定
__aenter__
と__aexit__
方法とモックClientSession
を書き込むとpatch
にnew
引数で使用します。
これらのどれも違いを生じないようです。私がアサーションをis_ok
に入れてClientSession
がMagicMock
のインスタンスであることをテストすると、テストを実行すると、これらのアサーションは失敗します(コードがパッチされていないときと同じです)。それは私の名前空間の不一致の理論につながります。つまり、イベントループはpatch
がターゲットとする別の名前空間で実行されています。
どちらか、または私は何か愚かなことをやっている!
それはひどいですが、OK ... – Xophmeister
これは、すべてのSQL実行を嘲笑するのではなく、テストデータベースの使用法と似ています。 –
ええと、統合テスト。あなたがコントロールフローをテストしたいと思うならば、理解でき、必要ですが、間違いなく過剰です。 – Xophmeister