Python 使用 pytest 的单元测试覆盖率

Python unit test coverage using pytest

我是 pytest 的新手,想为单元测试覆盖添加以下 3 种方法,而不是实际使用真正的 mongo 数据库实例,而是模拟它。 可以尝试使用真实的数据库实例,但不推荐这样做。 请求有关如何模拟 mongodb 客户端并获取文档的示例

import os
import logging
import urllib.parse
from dotenv import load_dotenv
from pymongo import MongoClient
from logger import *

load_dotenv()


def getMongoConnection():
    userName = urllib.parse.quote_plus(os.getenv("USER_NAME"))
    password = urllib.parse.quote_plus(os.getenv("PASSWORD"))
    hostName1_port = os.getenv("HOST_NAME1")
    hostName2_port = os.getenv("HOST_NAME2")
    hostName3_port = os.getenv("HOST_NAME3")
    authSourceDatabase = os.getenv("AUTH_SOURCE_DATABASE")
    replicaSet = os.getenv("REPLICA_SET")
    connectTimeoutMS = "1000"
    socketTimeoutMS = "30000"
    maxPoolSize = "100"

    try:
        client = MongoClient('mongodb://'+userName+':'+password+'@'+hostName1_port+','+hostName2_port+','+hostName3_port+'/'+authSourceDatabase+'?ssl=true&replicaSet='+replicaSet +
                             '&authSource='+authSourceDatabase+'&retryWrites=true&w=majority&connectTimeoutMS='+connectTimeoutMS+'&socketTimeoutMS='+socketTimeoutMS+'&maxPoolSize='+maxPoolSize)
        return client
    except Exception as e:
        logging.error("Error while connecting to mongoDB.")
        return False


def connectToDBCollection(client, databaseName, collectionName):
    db = client[databaseName]
    collection = db[collectionName]
    return collection


def getDoc(bucketName, databaseName, collectionName):
    try:
        client = getMongoConnection()
        if client != False:
            collection = connectToDBCollection(
                client, databaseName, collectionName)
            return collection.find_one({'bucket': bucketName})
    except Exception as e:
        logging.error("An exception occurred while fetching doc, error is ", e)

编辑:(尝试使用以下代码并能够涵盖大多数情况但看到错误)

def test_mongo():
    db_conn = mongomock.MongoClient()
    assert isinstance(getMongoConnection(), MongoClient)


def test_connect_mongo():
    return connectToDBCollection(mongomock.MongoClient(), "sampleDB", "sampleCollection")


//trying to cover exception block for getMongoConnection()
def test_exception():
    with pytest.raises(Exception) as excinfo:
        getMongoConnection()
    assert str(excinfo.value) == False


def test_getDoc():
    collection = mongomock.MongoClient().db.collection
    stored_obj = collection.find_one({'_id': 1})
    assert stored_obj == getDoc("bucket", "db", "collection")


def test_createDoc():
    collection = mongomock.MongoClient().db.collection
    stored_obj = collection.insert_one({'_id': 1})
    assert stored_obj == createDoc("bucket", "db", "collection")


def test_updateDoc():
    collection = mongomock.MongoClient().db.collection
    stored_obj = collection.replace_one({'_id': 1}, {'_id': 2})
    assert stored_obj == updateDoc(
        {'_id': 1}, {'$set': {'_id': 2}}, "db", "collection")

错误: test_exception - 失败:没有提高 test_createDoc - 类型错误:并非所有参数都在字符串格式化期间转换 AssertionError: assert ==

看起来 MongoClient 是一个带有 databaseNamecollectionName 的嵌套字典,或者是使用键访问器实现的。

你可以先模拟客户端

import unittest
mocked_collection = unittest.mock.MagicMock()
# mock the find_one method
mocked_collection.find_one.return_value = {'data': 'collection_find_one_result'}
mocked_client = unittest.mock.patch('pymongo.MongoClient').start()
mocked_client.return_value = {
    'databaseName': {'collectionname': mocked_collection}
}

也许可以尝试像 MongoMock 这样的专门模拟库?

特别是最后一个使用 @mongomock.patch 的示例看起来可能与您的代码相关。