【问题标题】:How to implement pytest for FastAPI with MongoDB(Motor)如何使用 MongoDB(Motor) 为 FastAPI 实现 pytest
【发布时间】:2022-07-15 00:17:27
【问题描述】:

我想为我的 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

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

我想用fake DB进行测试,比如json文件

db = {
todos: [...]
}

【问题讨论】:

  • 最好的方法是在 mongodb 中用一个测试数据库测试端点,这样您就可以确定它们按您的预期工作。下一种可能性是模拟您的集合查询或创建一个允许遵循 mongodb 集合 API 的某些操作的假货。更好的解决方案是将您的实际 mongdb 查询移动到您使用 Depends 注入到您的视图中的专用服务,然后模拟此服务以返回一组在 json 文件中定义的数据。但首先:所有这些间接真的是必要的吗?首先使用真正的 mongodb 运行测试
  • 所以如果我在真正的 MongoDB 上运行我的测试,你知道我应该如何跳过取决于吗?使用假令牌进行测试?
  • 你在考虑用户依赖吗?还是别的什么?
  • 关于用户依赖
  • 您可以让您的应用程序允许添加用户并以用户身份进行身份验证(即真实方式),或者您可以使用app.dependency_overrides 提供一个自定义函数,该函数在您的测试。 fastapi.tiangolo.com/advanced/testing-dependencies - app.dependency_overrides[get_current_user] = lambda: return {'id': 1, 'username': 'foo'}

标签: mongodb unit-testing pytest fastapi mongomock


【解决方案1】:

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

这里是如何在 FastAPI 中简单地应用后一种方法;

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

conftest.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'

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多