FastAPI - 向 TestClient 添加路由前缀
FastAPI - adding route prefix to TestClient
我有一个 FastAPI 应用,其路由前缀为 /api/v1
。
当我 运行 测试时它抛出 404
。我看到这是因为 TestClient
无法在 /ping
找到路由,并且当测试用例中的路由更改为 /api/v1/ping
.
时可以正常工作
有没有一种方法可以避免根据前缀更改所有测试函数中的所有路由?这似乎很麻烦,因为有很多测试用例,也因为我不想在我的测试用例中硬编码依赖路由前缀。有没有一种方法可以像在 app
中那样在 TestClient
中配置前缀,并像在 routes.py
中提到的那样简单地提及路由?
routes.py
from fastapi import APIRouter
router = APIRouter()
@router.get("/ping")
async def ping_check():
return {"msg": "pong"}
main.py
from fastapi import FastAPI
from routes import router
app = FastAPI()
app.include_router(prefix="/api/v1")
在我的测试文件中:
test.py
from main import app
from fastapi.testclient import TestClient
client = TestClient(app)
def test_ping():
response = client.get("/ping")
assert response.status_code == 200
assert response.json() == {"msg": "pong"}
找到解决方法。
TestClient
有一个接受 base_url
的选项,然后 urljoin
使用路由 path
编辑。所以我将路由前缀附加到此 base_url
.
url = urljoin(self.base_url, url)
但是,这有一个问题 - urljoin
仅当 base_url
以 /
结尾且path
不以 /
开头。 This SO answer 解释得很好。
这导致了以下变化:
test.py
from main import app, ROUTE_PREFIX
from fastapi.testclient import TestClient
client = TestClient(app)
client.base_url += ROUTE_PREFIX # adding prefix
client.base_url = client.base_url.rstrip("/") + "/" # making sure we have 1 and only 1 `/`
def test_ping():
response = client.get("ping") # notice the path no more begins with a `/`
assert response.status_code == 200
assert response.json() == {"msg": "pong"}
上面的 work-around(Shod 的)对我有用,但我必须将 APIRouter 对象而不是 FastAPI 对象传递给测试客户端。否则我会收到 404 错误。
下面是它如何为我工作的示例代码。
from fastapi import FastAPI, APIRouter
from fastapi.testclient import TestClient
app = FastAPI()
router = APIRouter(prefix="/sample")
app.include_router(router)
@router.post("/s1")
def read_main():
return {"msg": "Hello World"}
client = TestClient(router)
client.base_url += "/sample"
client.base_url = client.base_url.rstrip("/") + "/"
def test_main():
response = client.post("s1")
assert response.status_code == 200
assert response.json() == {"msg": "Hello World"}
我有一个 FastAPI 应用,其路由前缀为 /api/v1
。
当我 运行 测试时它抛出 404
。我看到这是因为 TestClient
无法在 /ping
找到路由,并且当测试用例中的路由更改为 /api/v1/ping
.
有没有一种方法可以避免根据前缀更改所有测试函数中的所有路由?这似乎很麻烦,因为有很多测试用例,也因为我不想在我的测试用例中硬编码依赖路由前缀。有没有一种方法可以像在 app
中那样在 TestClient
中配置前缀,并像在 routes.py
中提到的那样简单地提及路由?
routes.py
from fastapi import APIRouter
router = APIRouter()
@router.get("/ping")
async def ping_check():
return {"msg": "pong"}
main.py
from fastapi import FastAPI
from routes import router
app = FastAPI()
app.include_router(prefix="/api/v1")
在我的测试文件中:
test.py
from main import app
from fastapi.testclient import TestClient
client = TestClient(app)
def test_ping():
response = client.get("/ping")
assert response.status_code == 200
assert response.json() == {"msg": "pong"}
找到解决方法。
TestClient
有一个接受 base_url
的选项,然后 urljoin
使用路由 path
编辑。所以我将路由前缀附加到此 base_url
.
url = urljoin(self.base_url, url)
但是,这有一个问题 - urljoin
仅当 base_url
以 /
结尾且path
不以 /
开头。 This SO answer 解释得很好。
这导致了以下变化:
test.py
from main import app, ROUTE_PREFIX
from fastapi.testclient import TestClient
client = TestClient(app)
client.base_url += ROUTE_PREFIX # adding prefix
client.base_url = client.base_url.rstrip("/") + "/" # making sure we have 1 and only 1 `/`
def test_ping():
response = client.get("ping") # notice the path no more begins with a `/`
assert response.status_code == 200
assert response.json() == {"msg": "pong"}
上面的 work-around(Shod 的)对我有用,但我必须将 APIRouter 对象而不是 FastAPI 对象传递给测试客户端。否则我会收到 404 错误。 下面是它如何为我工作的示例代码。
from fastapi import FastAPI, APIRouter
from fastapi.testclient import TestClient
app = FastAPI()
router = APIRouter(prefix="/sample")
app.include_router(router)
@router.post("/s1")
def read_main():
return {"msg": "Hello World"}
client = TestClient(router)
client.base_url += "/sample"
client.base_url = client.base_url.rstrip("/") + "/"
def test_main():
response = client.post("s1")
assert response.status_code == 200
assert response.json() == {"msg": "Hello World"}