我正在嘗試修補/模擬AsyncHTTPClient.fetch在我的程式的兩個不同位置呼叫的方法 ():首先tornado_openapi3.testing在my_file. 問題是該方法正在第一個位置進行修補,這破壞了我的測驗功能。
我的檔案.py:
import tornado
class Handler(tornado.web.RequestHandler, ABC):
def initialize(self):
<some_code>
async def get(self, id):
<some_code>
client = AsyncHTTPClient()
response = await client.fetch(<some_path>)
<some_code>
test_handler.py:
from tornado_openapi3.testing import AsyncOpenAPITestCase
class HandlerTestCase(AsyncOpenAPITestCase):
def get_app(self) -> Application:
return <some_app>
def test_my_handler(self):
with patch.object(my_file.AsyncHTTPClient, 'fetch') as mock_fetch:
f = asyncio.Future()
f.set_result('some_result_for_testing')
mock_fetch.return_value = f
self.fetch(<some_path>)
根據我從各種模擬教程(例如https://docs.python.org/3/library/unittest.mock.html)中了解到的,fetch應該只在my_file. 我怎樣才能確保是這種情況?
uj5u.com熱心網友回復:
問題的原因
里面的匯入類AsyncHTTPClient其實my_file.py只是對tornado原有AsyncHTTPClient類的參考。
基本上,from x import y陳述句是變數賦值,因為y在參考原始物件的當前檔案中創建了一個名為的新變數x.y。
而且,由于類是可變物件,因此當您修補fetch匯入類中的方法時,實際上是在修補fetch原始類上的方法。
下面是一個使用變數賦值的例子來說明這個問題:
class A:
x = 1
b = A # create a variable 'b' referencing the class 'A'
b.x = 2 # change the value of 'x' attribute' of 'b'
print(A.x)
# Outputs -> 2 (not 1 because classes are mutable)
就像我之前說的,from ... import ...陳述句基本上是變數賦值。所以上面的插圖是你修補fetch方法時真正發生的事情。
解決方案
不要修補單個方法,而是修補整個類:
with patch.object(my_file, 'AsyncHTTPClient') as mock_client:
f = asyncio.Future()
f.set_result('some_result_for_testing')
mock_client.fetch.return_value = f
self.fetch(<some_path>)
這次發生的事情是 Python 正在將區域變數的值重新分配AsyncHTTPClient給模擬物件。這次沒有發生突變,因此原始類不受影響。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/470389.html
