簡體   English   中英

使用unittest.mock.patch測試aiohttp客戶端

[英]Testing aiohttp client with unittest.mock.patch

我用aiohttp編寫了一個簡單的HTTP客戶端,我試圖通過修補aiohttp.ClientSessionaiohttp.ClientResponse來測試它。 但是,似乎unittest.mock.patch裝飾器不尊重我的異步代碼。 猜測一下,我會說它是某種名稱空間不匹配。

這是一個最小的例子:

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)

我正在使用異步裝飾器進行測試,如本答案中所述 所以這是我的嘗試測試:

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協程在__main__使用時工作正常,但是當我運行測試時,它會給我一個錯誤,表明我的patch調用沒有模擬session.request函數。 (特別是它說“無法解析來自URL'foo'的主機名”,如果它沒有被模擬,它就應該這樣 。)

我無法逃避這種行為。 我努力了:

  • is_ok后導入is_ok
  • 分配到嘲笑的各種組合mock_clientmock_client.__aenter__ ,設置mock_client.requestMagicMock(return_value=mock_response)或使用mock_client().request
  • 使用特定的__aenter____aexit__方法編寫模擬ClientSession ,並在new參數中使用它進行patch

這些似乎沒有任何區別。 如果我將斷言放入is_ok來測試ClientSessionMagicMock一個實例,那么當我運行測試時這些斷言就會失敗(同樣,當代碼沒有被修補時它們也會失敗)。 這導致了我的命名空間不匹配理論:即,事件循環運行在patch所針對的不同命名空間中。

不管怎樣,或者我做了些蠢事!

不建議使用模擬ClientSession

推薦的方法是創建虛假服務器並向其發送實際請求。

看一下aiohttp的例子

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM