如何使用 MongoDB(Motor) 实现 FastAPI 的 pytest

Joh*_*ohn 5 unit-testing mongodb pytest mongomock fastapi

我想为我的 FastAPI 端点编写测试

我的代码示例:

from fastapi import FastAPI
from fastapi.testclient import TestClient

app = FastAPI()

@app.get("/todos")
async def get_todo_by_title(title: str,current_user: User = Depends(get_current_user))
    document = await collection.find_one({"title": title})
    return document

client = TestClient(app)

def test_get_todo_by_title():
    response = client.get("/todos")
    assert response.status_code == 200
Run Code Online (Sandbox Code Playgroud)

测试我的端点的最佳方法是什么?

我想使用假数据库进行测试,例如 json 文件

db = {
todos: [...]
}
Run Code Online (Sandbox Code Playgroud)

小智 4

使用 JSON 文件中的虚假数据并不是最佳选择。相反,您可以使用测试数据库(基于您运行应用程序的环境)或任何其他数据库(dev、stg、..等),并在运行所有单元测试后删除测试数据。

下面是如何在 FastAPI 中简单应用后一种方法;

  • 假设您有 3 个简单的表(或集合)X、Y 和 Z
  • MongoDB 是数据库服务
  • PyTest 是测试引擎

测试.py

from pytest import fixture
from starlette.config import environ
from starlette.testclient import TestClient
from config.db_connection import database, X_collection, Y_collection, Z_collection


@fixture(scope="session")
def test_X():
    return {
        "_id": "10",
        "name": "test",
        "description": "test",
        "type": "single value",
        "crt_at": "2022-06-27T12:23:15.143Z",
        "upd_at": "2022-06-27T12:23:15.143Z"
    }

//test_Y and test_Z fixtures should be like test_X


@fixture(scope="session", autouse=True)
def test_client(test_X, test_Y, test_Z):
    import main
    application = main.app
    with TestClient(application) as test_client:
        yield test_client

    db = database
    //Here, delete any objects you have created for your tests
    db[X_collection].delete_one({"_id": test_X["_id"]})
    db[Y_collection].delete_one({"_id": test_Y["_id"]})
    db[Z_collection].delete_one({"_id": test_Z["_id"]})


environ['TESTING'] = 'TRUE'
Run Code Online (Sandbox Code Playgroud)

单元测试应类似于以下示例。

test_X_endpoints.py

def test_create_X(test_client, test_X):
    response = test_client.post("/create_X_URI/", json=test_X)
    assert response.status_code == 201
    //Add assertions as needed

def test_list_X(test_client):
    response = test_client.get("/list_X_objects_URI/?page=1&size=1")
    assert response.status_code == 200
    //Add assertions as needed
Run Code Online (Sandbox Code Playgroud)