测试AsyncIO MongoDB函数(Asyncio Motor Driver)

vzgqcmou  于 2023-05-22  发布在  Go
关注(0)|答案(1)|浏览(132)

我对AsyncIO很陌生,希望能得到一些帮助。我有一个运行聚合管道的基本类,它在生产中运行得很好:

class BasePipeline2:
    client: motor.AsyncIOMotorClient
    db: motor.AsyncIOMotorDatabase
    collection: motor.AsyncIOMotorCollection

    def __init__(self, uri: str, database: str, collection: str):
        self.client = get_client(uri)
        self.db = self.client[database]
        self.collection = self.db[collection]

    async def run(self):
        """Runs the pipeline and returns the results as a list"""
        result = await self.collection.aggregate({"$match": {"foo": "bar"}}).to_list(length=None)
        return result

我介绍了以下测试:

@pytest.mark.asyncio
async def test_run2(self):
    results = [{"_id": 1, "name": "Alice", "age": 25}, {"_id": 2, "name": "Bob", "age": 30}]
    cursor_mock = mock.AsyncMock()
    cursor_mock.to_list = mock.AsyncMock(return_value=results)

    collection_mock = mock.MagicMock()
    collection_mock.aggregate = mock.AsyncMock(return_value=cursor_mock)

    pipeline = BasePipeline2("mongodb://localhost:27017/", "test_db", "test_collection")
    with mock.patch.object(pipeline, "collection", collection_mock):
        pipeline_result = await pipeline.run()

    assert pipeline_result == results

我试图模拟to_list方法来返回测试结果。然而,无论我怎么尝试,我都会得到一个错误:

AttributeError: 'coroutine' object has no attribute 'to_list'

我似乎找不到解决方案,我觉得问题出在我设置模拟的方式上。

m3eecexj

m3eecexj1#

如果其他人看到这个:这是模拟设置方式的问题。对我有效的正确测试:

@pytest.mark.asyncio
async def test_run2(self):
    results = [{"_id": 1, "name": "Alice", "age": 25}, {"_id": 2, "name": "Bob", "age": 30}]
    cursor_mock = mock.AsyncMock()
    cursor_mock.to_list = mock.AsyncMock(return_value=results)

    collection_mock = mock.MagicMock()
    collection_mock.aggregate = mock.AsyncMock(return_value=cursor_mock)

    pipeline = BasePipeline2("mongodb://localhost:27017/", "test_db", "test_collection")
    with mock.patch.object(pipeline.collection, "aggregate", return_value=cursor_mock) as aggregate_mock:
        pipeline_result = await pipeline.run()

    aggregate_mock.assert_called_once_with({"$match": {"foo": "bar"}})
    cursor_mock.to_list.assert_awaited()
    assert pipeline_result == results

注意修补with mock.patch.object(pipeline.collection, "aggregate", return_value=cursor_mock),它修补aggregate方法以返回模拟游标。

相关问题