![](/img/trans.png)
[英]Use requests-html to test Flask app without starting server
[英]Unit test a listener in Sanic without starting the app server
假設我在我的 Sanic 應用程序中定義了這個監聽器:
@app.before_server_start
async def db_setup(*args):
# ... set up the DB as I wish for the app
如果我想對這個 function (使用 pytest)進行單元測試,並將其導入到帶有from my.app import db_setup
的單元測試文件中,似乎測試實際上開始為應用程序提供服務,因為 pytest 輸出:
[INFO] Goin' Fast @ http://0.0.0.0:8000
[INFO] Starting worker [485]
現在,我知道我可以通過執行db_setup = db_setup.__wrapped__
來移除裝飾器的效果,但為了做到這一點,我實際上需要導入db_setup
,這是 Sanic 服務器啟動的地方。
有沒有辦法在導入時消除裝飾器的影響?
LE:我嘗試如下修補 Sanic 應用程序:
async def test_stuff(mocker):
mocker.patch('myapp.app.app') # last '.app' being `app = Sanic('MyApp')`
imp = importlib.import_module('myapp.app')
db_setup = getattr(imp, 'db_setup')
await db_setup()
但現在我得到一個RuntimeError: Cannot run the event loop while another loop is running
為mocker.patch('myapp.app.app')
行運行。
我將在這里做一些假設,所以如果有一些澄清,我可能需要修改這個答案。
在開始之前,需要注意的是裝飾器本身不會啟動你的 web 服務器。 這將在以下兩種情況之一中運行:
app.run()
TestClient
,它專門通過運行應用程序的 web 服務器來運行現在,據我所知,您正在嘗試通過將其稱為 function 手動在測試中運行db_setup
,但您不希望它在測試中作為偵聽器附加到應用程序。
您可以在app.listeners
屬性中訪問所有應用程序實例的偵聽器。 因此,一種解決方案是這樣的:
# conftest.py
import pytest
from some.place import app as myapp
@pytest.fixture
def app():
myapp.listeners = {}
return myapp
就像我之前說的,這只會清空你的聽眾。 它實際上不會影響您的應用程序啟動,因此我不確定它是否具有您正在尋找的實用程序。
你應該能夠擁有這樣的東西:
from unittest.mock import Mock
import pytest
from sanic import Request, Sanic, json
app = Sanic(__name__)
@app.get("/")
async def handler(request: Request):
return json({"foo": "bar"})
@app.before_server_start
async def db_setup(app, _):
app.ctx.db = 999
@pytest.mark.asyncio
async def test_sample():
await db_setup(app, Mock())
assert app.ctx.db == 999
為了方便起見,它們都在同一個 scope 中,但即使測試函數、應用程序實例和偵聽器分布在不同的模塊中,最終結果也是一樣的:您可以像運行任何其他db_setup
一樣運行 db_setup 和是否注冊為偵聽器都沒有關系。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.