使用Motor AsyncIO和Pytest测试MongoDB功能

2024-05-23 19:03:13 发布

您现在位置:Python中文网/ 问答频道 /正文

因此,我尝试编写几个测试来测试使用异步MongoDB连接的函数。要连接到MongoDB,我使用带asyncio的Motor。我需要帮助模拟电机连接

我的代码:

commons.py

mongo = None

黑名单.py

import commons

class Blacklist(object):
    async def check_if_blacklisted(self, word: str):
        blacklisted = False
        if await commons.mongo.dbtest.blacklist.find_one({'word': word}):
            blacklisted = True
        return blacklisted

main.py

import asyncio
from blacklist import Blacklist
from motor.motor_asyncio import AsyncIOMotorClient
import commons

async def run():
    commons.mongo = AsyncIOMotorClient("mongodb://localhost", io_loop=asyncio.get_event_loop())
    blacklist_checker = Blacklist()
    result = await blacklist_checker.check_if_blacklisted(word="should_be_false")
    print(result)
    # > False

    result = await blacklist_checker.check_if_blacklisted(word="should_be_true")
    print(result)
    # > True

loop = asyncio.get_event_loop()
loop.run_until_complete(run())
loop.close()

我现在想通过模拟电机连接来测试blacklist.py,但我似乎无法使测试正常运行。以下是我尝试过的代码:

测试黑名单.py

import pytest
from blacklist import Blacklist

class TestBlacklist(object):

@pytest.fixture
async def motor(self, event_loop):
    # I know I'm not mocking the Motor Connection here, 
    # but just wanted to show you the output using this fixture.
    commons.mongo = motor.motor_asyncio.AsyncIOMotorClient(io_loop=event_loop)
    yield commons.mongo
    commons.mongo.close()

@pytest.mark.asyncio
async def test_check_if_blacklisted(self):
    blacklist_checker = Blacklist()
    blacklisted = await blacklist_checker.check_if_blacklisted(word="should_be_false")
    assert blacklisted == False
    # > AttributeError: 'NoneType' object has no attribute 'blacklist'

pytest mongodb:

import pytest
from unittest.mock import patch
from blacklist import Blacklist

class TestBlacklist(object):

    @pytest.mark.asyncio
    async def test_check_if_blacklisted(self, mongodb):
        with patch("blacklist.commons.mongo") as db:
            db = mongodb
            blacklist_checker = Blacklist()
            blacklisted = await blacklist_checker.check_if_blacklisted(word="should_be_false")
        assert blacklisted == False
        # > TypeError: object MagicMock can't be used in 'await' expression

我尝试在线搜索,但找不到合适的线程来帮助我在模拟异步电机连接时执行测试。此外,如果您认为我的测试方向不正确,请告诉我,因为我是编写测试的新手,尤其是异步db连接

注意:blacklist.py有各种需要MongoDB功能的函数,因此如果在我的测试中\u blacklist.py我可以初始化commons.mongo一次,并且所有后续测试都使用它,那就太好了


Tags: pyimportloopasyncioifpytestmongocheck
1条回答
网友
1楼 · 发布于 2024-05-23 19:03:13

您可以使用pytest async MongoDB模拟异步MongoDB数据库,但请记住它已经过时,并且存在依赖项错误,因此您必须按照以下方式修复依赖项版本:

mongomock==3.12.0
pyyaml==3.13
pytest-asyncio==0.10.0
pytest==3.6.4

使用pytest async mongodb可以通过添加名为async\u mongodb的参数,在测试中获得模拟数据库。 我会告诉你代码和结构

project
  -app
    __init__.py
    blacklist.py
    commons.py
  -test
    -fixtures
      blacklist.json
    __init__.py
    test_blacklist.py
  main.py
  pytest.ini

main.py

import asyncio
from app.blacklist import Blacklist
from app.commons import get_database, set_client
from motor.motor_asyncio import AsyncIOMotorClient


async def run():
    set_client(
        AsyncIOMotorClient("mongodb://localhost", io_loop=asyncio.get_event_loop())
    )
    db = await get_database()
    blacklist_checker = Blacklist()
    result = await blacklist_checker.check_if_blacklisted(db, word="should_be_false")
    print(result)
    # > False

    result = await blacklist_checker.check_if_blacklisted(db, word="should_be_true")
    print(result)
    # > True


loop = asyncio.get_event_loop()
loop.run_until_complete(run())
loop.close()

黑名单.py

from motor.motor_asyncio import AsyncIOMotorDatabase


class Blacklist(object):
    async def check_if_blacklisted(self, db: AsyncIOMotorDatabase, word: str):
        blacklisted = False
        if await db.blacklist.find_one({"word": word}):
            blacklisted = True
        return blacklisted

commons.py

from motor.motor_asyncio import AsyncIOMotorClient, AsyncIOMotorDatabase


class DataBase:
    client: AsyncIOMotorClient = None


db = DataBase()


async def get_database() -> AsyncIOMotorDatabase:
    return db.client["dbtest"]


def set_client(client):
    db.client = client

测试黑名单.py

import pytest
from app import blacklist


@pytest.mark.asyncio
async def test_should_be_false(async_mongodb):
    blacklist_checker = blacklist.Blacklist()
    blacklisted = await blacklist_checker.check_if_blacklisted(
        async_mongodb, word="should_be_false"
    )
    assert blacklisted == False


@pytest.mark.asyncio
async def test_should_be_true(async_mongodb):
    blacklist_checker = blacklist.Blacklist()
    blacklisted = await blacklist_checker.check_if_blacklisted(
        async_mongodb, word="should_be_true"
    )
    assert blacklisted == True

pytest.ini

[pytest]
async_mongodb_fixture_dir =
  test/fixtures

async_mongodb_fixtures =
  blacklist

blacklist.json

[
    {
      "_id": {"$oid": "60511d158f80a8d34986e2b0"},
      "word" : "should_be_true"
    }
]

夹具也可以是.yaml,可以定义所需的数量。阅读package documentation了解更多信息

因为它已经过时了,所以我创建了一个fork来更新它并用新特性改进它。我们邀请您查看它,如果您愿意,可以使用它

相关问题 更多 >