简体   繁体   English

如何为 python 单元测试模拟 mongodb?

[英]How to mock mongodb for python unittests?

I am using mock module for Python 2.7 to mock my other functions and using我正在使用 Python 2.7 的mock模块来模拟我的其他功能并使用

unittest for writing unit tests. unittest用于编写单元测试。

I am wondering if mocking the MongoDB is different than using mock functionality ( mock.patch a function that is being called?) Or I need to use another different package for that purpose?我想知道 mocking MongoDB 是否不同于使用模拟功能( mock.patch a function 被调用?)或者我需要为此目的使用另一个不同的 package 吗?

I do not think I want to have a test mongodb instance running.我不认为我想要运行测试 mongodb 实例。 All I want is some tempo data and being able to call pymongo functionality.我想要的只是一些节奏数据并能够调用pymongo功能。 I am just a bit lost in thinking of is there a way to write a mock for a module (like pymongo ), or anything is achievable by mock module.我只是有点迷失在想是否有一种方法可以为模块编写模拟(如pymongo ),或者mock模块可以实现任何东西。

So appreciate if you could provide an example or tutorial on this.如果您能提供有关此的示例或教程,我们将不胜感激。

Code to Test测试代码

from pymongo import MongoClient

monog_url = 'mongodb://localhost:27017'
client = MongoClient(monog_url)
db = client.db

class Dao(object):
   def __init__(self):
      pass

   def save(self, user):
      db_doc = {
        'name': user.name,
        'email': user.email
      }
      db.users.save(db_doc)

   def getbyname(self, user):
      db_doc = {
        'name': user.name,
      }
      return db.users.find(db_doc)

To test this, I do not really want a test mongodb up and running, But also.要测试这个,我不是很想测试mongodb up and running,但是也是。 I think I do not want to mock db.userssave and db.users.find because I want to actually be able to retrieve the data that I saved and make sure it is in the db.我想我不想模拟 db.userssave 和 db.users.find 因为我想实际上能够检索我保存的数据并确保它在数据库中。 I think I need to create some fixtures per models that are in my memory and work with them.我想我需要为我的 memory 中的每个模型创建一些固定装置并使用它们。 Just do I need an external tool to do so?只是我需要一个外部工具吗?

I am thinking of keeping some fake data like this, just do not know how to properly deal with it.我正在考虑保留一些这样的假数据,只是不知道如何正确处理它。

users = { 
    {'name' : 'Kelly', 'email' : 'kelly@gmail.com'},
    {'name': 'Sam', 'email': 'sam@gmail.com'}
}

I am using mock module for Python 2.7 to mock my other functions and using我正在使用 Python 2.7 的mock模块来模拟我的其他功能并使用

unittest for writing unit tests. unittest用于编写单元测试。

I am wondering if mocking the MongoDB is different than using mock functionality ( mock.patch a function that is being called?) Or I need to use another different package for that purpose?我想知道模拟 MongoDB 是否与使用模拟功能不同( mock.patch一个正在调用的函数?)或者我需要为此使用另一个不同的包?

I do not think I want to have a test mongodb instance running.我不认为我想要运行测试 mongodb 实例。 All I want is some tempo data and being able to call pymongo functionality.我想要的只是一些节奏数据并能够调用pymongo功能。 I am just a bit lost in thinking of is there a way to write a mock for a module (like pymongo ), or anything is achievable by mock module.我只是有点迷失在思考是否有办法为模块(如pymongo )编写模拟,或者mock模块可以实现任何事情。

So appreciate if you could provide an example or tutorial on this.如果您能提供有关此的示例或教程,请感谢。

Code to Test要测试的代码

from pymongo import MongoClient

monog_url = 'mongodb://localhost:27017'
client = MongoClient(monog_url)
db = client.db

class Dao(object):
   def __init__(self):
      pass

   def save(self, user):
      db_doc = {
        'name': user.name,
        'email': user.email
      }
      db.users.save(db_doc)

   def getbyname(self, user):
      db_doc = {
        'name': user.name,
      }
      return db.users.find(db_doc)

To test this, I do not really want a test mongodb up and running!为了测试这个,我真的不想要一个测试 mongodb 启动并运行! But also, I think I do not want to mock db.userssave and db.users.find because I want to actually be able to retrieve the data that I saved and make sure it is in the db.而且,我想我不想模拟 db.userssave 和 db.users.find 因为我希望实际上能够检索我保存的数据并确保它在数据库中。 I think I need to create some fixtures per models that are in my memory and work with them.我想我需要为我记忆中的每个模型创建一些装置并使用它们。 Just do I need an external tool to do so?我只需要一个外部工具来做到这一点吗?

I am thinking of keeping some fake data like this, just do not know how to properly deal with it.我想保留一些这样的假数据,只是不知道如何妥善处理。

users = { 
    {'name' : 'Kelly', 'email' : 'kelly@gmail.com'},
    {'name': 'Sam', 'email': 'sam@gmail.com'}
}

I am using mock module for Python 2.7 to mock my other functions and using我正在使用 Python 2.7 的mock模块来模拟我的其他功能并使用

unittest for writing unit tests. unittest用于编写单元测试。

I am wondering if mocking the MongoDB is different than using mock functionality ( mock.patch a function that is being called?) Or I need to use another different package for that purpose?我想知道模拟 MongoDB 是否与使用模拟功能不同( mock.patch一个正在调用的函数?)或者我需要为此使用另一个不同的包?

I do not think I want to have a test mongodb instance running.我不认为我想要运行测试 mongodb 实例。 All I want is some tempo data and being able to call pymongo functionality.我想要的只是一些节奏数据并能够调用pymongo功能。 I am just a bit lost in thinking of is there a way to write a mock for a module (like pymongo ), or anything is achievable by mock module.我只是有点迷失在思考是否有办法为模块(如pymongo )编写模拟,或者mock模块可以实现任何事情。

So appreciate if you could provide an example or tutorial on this.如果您能提供有关此的示例或教程,请感谢。

Code to Test要测试的代码

from pymongo import MongoClient

monog_url = 'mongodb://localhost:27017'
client = MongoClient(monog_url)
db = client.db

class Dao(object):
   def __init__(self):
      pass

   def save(self, user):
      db_doc = {
        'name': user.name,
        'email': user.email
      }
      db.users.save(db_doc)

   def getbyname(self, user):
      db_doc = {
        'name': user.name,
      }
      return db.users.find(db_doc)

To test this, I do not really want a test mongodb up and running!为了测试这个,我真的不想要一个测试 mongodb 启动并运行! But also, I think I do not want to mock db.userssave and db.users.find because I want to actually be able to retrieve the data that I saved and make sure it is in the db.而且,我想我不想模拟 db.userssave 和 db.users.find 因为我希望实际上能够检索我保存的数据并确保它在数据库中。 I think I need to create some fixtures per models that are in my memory and work with them.我想我需要为我记忆中的每个模型创建一些装置并使用它们。 Just do I need an external tool to do so?我只需要一个外部工具来做到这一点吗?

I am thinking of keeping some fake data like this, just do not know how to properly deal with it.我想保留一些这样的假数据,只是不知道如何妥善处理。

users = { 
    {'name' : 'Kelly', 'email' : 'kelly@gmail.com'},
    {'name': 'Sam', 'email': 'sam@gmail.com'}
}

I am using mock module for Python 2.7 to mock my other functions and using我正在使用 Python 2.7 的mock模块来模拟我的其他功能并使用

unittest for writing unit tests. unittest用于编写单元测试。

I am wondering if mocking the MongoDB is different than using mock functionality ( mock.patch a function that is being called?) Or I need to use another different package for that purpose?我想知道模拟 MongoDB 是否与使用模拟功能不同( mock.patch一个正在调用的函数?)或者我需要为此使用另一个不同的包?

I do not think I want to have a test mongodb instance running.我不认为我想要运行测试 mongodb 实例。 All I want is some tempo data and being able to call pymongo functionality.我想要的只是一些节奏数据并能够调用pymongo功能。 I am just a bit lost in thinking of is there a way to write a mock for a module (like pymongo ), or anything is achievable by mock module.我只是有点迷失在思考是否有办法为模块(如pymongo )编写模拟,或者mock模块可以实现任何事情。

So appreciate if you could provide an example or tutorial on this.如果您能提供有关此的示例或教程,请感谢。

Code to Test要测试的代码

from pymongo import MongoClient

monog_url = 'mongodb://localhost:27017'
client = MongoClient(monog_url)
db = client.db

class Dao(object):
   def __init__(self):
      pass

   def save(self, user):
      db_doc = {
        'name': user.name,
        'email': user.email
      }
      db.users.save(db_doc)

   def getbyname(self, user):
      db_doc = {
        'name': user.name,
      }
      return db.users.find(db_doc)

To test this, I do not really want a test mongodb up and running!为了测试这个,我真的不想要一个测试 mongodb 启动并运行! But also, I think I do not want to mock db.userssave and db.users.find because I want to actually be able to retrieve the data that I saved and make sure it is in the db.而且,我想我不想模拟 db.userssave 和 db.users.find 因为我希望实际上能够检索我保存的数据并确保它在数据库中。 I think I need to create some fixtures per models that are in my memory and work with them.我想我需要为我记忆中的每个模型创建一些装置并使用它们。 Just do I need an external tool to do so?我只需要一个外部工具来做到这一点吗?

I am thinking of keeping some fake data like this, just do not know how to properly deal with it.我想保留一些这样的假数据,只是不知道如何妥善处理。

users = { 
    {'name' : 'Kelly', 'email' : 'kelly@gmail.com'},
    {'name': 'Sam', 'email': 'sam@gmail.com'}
}

I am using mock module for Python 2.7 to mock my other functions and using我正在使用 Python 2.7 的mock模块来模拟我的其他功能并使用

unittest for writing unit tests. unittest用于编写单元测试。

I am wondering if mocking the MongoDB is different than using mock functionality ( mock.patch a function that is being called?) Or I need to use another different package for that purpose?我想知道模拟 MongoDB 是否与使用模拟功能不同( mock.patch一个正在调用的函数?)或者我需要为此使用另一个不同的包?

I do not think I want to have a test mongodb instance running.我不认为我想要运行测试 mongodb 实例。 All I want is some tempo data and being able to call pymongo functionality.我想要的只是一些节奏数据并能够调用pymongo功能。 I am just a bit lost in thinking of is there a way to write a mock for a module (like pymongo ), or anything is achievable by mock module.我只是有点迷失在思考是否有办法为模块(如pymongo )编写模拟,或者mock模块可以实现任何事情。

So appreciate if you could provide an example or tutorial on this.如果您能提供有关此的示例或教程,请感谢。

Code to Test要测试的代码

from pymongo import MongoClient

monog_url = 'mongodb://localhost:27017'
client = MongoClient(monog_url)
db = client.db

class Dao(object):
   def __init__(self):
      pass

   def save(self, user):
      db_doc = {
        'name': user.name,
        'email': user.email
      }
      db.users.save(db_doc)

   def getbyname(self, user):
      db_doc = {
        'name': user.name,
      }
      return db.users.find(db_doc)

To test this, I do not really want a test mongodb up and running!为了测试这个,我真的不想要一个测试 mongodb 启动并运行! But also, I think I do not want to mock db.userssave and db.users.find because I want to actually be able to retrieve the data that I saved and make sure it is in the db.而且,我想我不想模拟 db.userssave 和 db.users.find 因为我希望实际上能够检索我保存的数据并确保它在数据库中。 I think I need to create some fixtures per models that are in my memory and work with them.我想我需要为我记忆中的每个模型创建一些装置并使用它们。 Just do I need an external tool to do so?我只需要一个外部工具来做到这一点吗?

I am thinking of keeping some fake data like this, just do not know how to properly deal with it.我想保留一些这样的假数据,只是不知道如何妥善处理。

users = { 
    {'name' : 'Kelly', 'email' : 'kelly@gmail.com'},
    {'name': 'Sam', 'email': 'sam@gmail.com'}
}

I am using mock module for Python 2.7 to mock my other functions and using我正在使用 Python 2.7 的mock模块来模拟我的其他功能并使用

unittest for writing unit tests. unittest用于编写单元测试。

I am wondering if mocking the MongoDB is different than using mock functionality ( mock.patch a function that is being called?) Or I need to use another different package for that purpose?我想知道模拟 MongoDB 是否与使用模拟功能不同( mock.patch一个正在调用的函数?)或者我需要为此使用另一个不同的包?

I do not think I want to have a test mongodb instance running.我不认为我想要运行测试 mongodb 实例。 All I want is some tempo data and being able to call pymongo functionality.我想要的只是一些节奏数据并能够调用pymongo功能。 I am just a bit lost in thinking of is there a way to write a mock for a module (like pymongo ), or anything is achievable by mock module.我只是有点迷失在思考是否有办法为模块(如pymongo )编写模拟,或者mock模块可以实现任何事情。

So appreciate if you could provide an example or tutorial on this.如果您能提供有关此的示例或教程,请感谢。

Code to Test要测试的代码

from pymongo import MongoClient

monog_url = 'mongodb://localhost:27017'
client = MongoClient(monog_url)
db = client.db

class Dao(object):
   def __init__(self):
      pass

   def save(self, user):
      db_doc = {
        'name': user.name,
        'email': user.email
      }
      db.users.save(db_doc)

   def getbyname(self, user):
      db_doc = {
        'name': user.name,
      }
      return db.users.find(db_doc)

To test this, I do not really want a test mongodb up and running!为了测试这个,我真的不想要一个测试 mongodb 启动并运行! But also, I think I do not want to mock db.userssave and db.users.find because I want to actually be able to retrieve the data that I saved and make sure it is in the db.而且,我想我不想模拟 db.userssave 和 db.users.find 因为我希望实际上能够检索我保存的数据并确保它在数据库中。 I think I need to create some fixtures per models that are in my memory and work with them.我想我需要为我记忆中的每个模型创建一些装置并使用它们。 Just do I need an external tool to do so?我只需要一个外部工具来做到这一点吗?

I am thinking of keeping some fake data like this, just do not know how to properly deal with it.我想保留一些这样的假数据,只是不知道如何妥善处理。

users = { 
    {'name' : 'Kelly', 'email' : 'kelly@gmail.com'},
    {'name': 'Sam', 'email': 'sam@gmail.com'}
}

Mongomock is recommended way for testing, here's a runnable example to get started:推荐使用Mongomock进行测试,下面是一个可运行的示例:

client.py客户端.py

from dataclasses import dataclass

import pymongo

monog_url = 'mongodb://localhost:27018'
client = pymongo.MongoClient(monog_url)
db = client.db


@dataclass
class User:
    name: str
    email: str


class Dao:

    def save(self, db, user):
        db_doc = {
            'name': user.name,
            'email': user.email
        }
        return db.users.insert_one(db_doc).inserted_id

    def get_by_name(self, db, user):
        db_doc = {
            'name': user.name,
        }
        return db.users.find(db_doc)

test_client.py test_client.py

import mongomock
import pytest

from client import Dao, User


class TestDao:

    @pytest.fixture
    def user(self):
        yield User(name='John', email='test@gmail.com')

    @pytest.fixture
    def dao(self):
        yield Dao()

    @pytest.fixture
    def client_mock(self):
        yield mongomock.MongoClient()

    @pytest.fixture
    def mock_db(self, client_mock):
        yield client_mock.db

    def test_save(self, mock_db, dao, user):
        id = dao.save(mock_db, user)

        users = list(mock_db.users.find())
        assert [obj for obj in users if obj['_id'] == id]
        assert len(users) == 1

    def test_get_by_name(self, mock_db, dao, user):
        dao.save(mock_db, user)
        found_user = next(dao.get_by_name(mock_db, user))
        found_user.pop('_id')
        assert found_user == user.__dict__

        unknown_user = User(name='Smith', email='john@gmail.com')
        found_user = next(dao.get_by_name(mock_db, unknown_user), None)
        assert found_user is None

Using @funnydman's example.使用@funnydman 的例子。

client.py客户端.py

from pymongo import MongoClient


class MongoDB(object):
    def __init__(self) -> None:
        self.MONGO_URI ='mongodb://localhost:27018' 
        self.client = MongoClient(self.MONGO_URI)
        self.default_db = self.client.db

    def ingest_one(self, document: any, collection_name: str, db_name: str = None):

        if document:
            db_name = self.client[db_name] if db_name else self.default_db
            return db_name[collection_name].insert_one(document).inserted_id

    def find(self, query: dict, collection_name: str, db_name: str = None):
        db_name = self.client[db_name] if db_name else self.default_db
        return db_name[collection_name].find(query)

test_client.py测试客户端.py

import mongomock
import pytest
import pytz
import datetime

from dataclasses import dataclass

from db.mongo_db import MongoDB


localtz = pytz.timezone('your_time_zone')


@dataclass
class Client:
    document: dict


class TestMongoDB:

    @pytest.fixture
    def client(self):
        yield Client(document={
            "name": "Juan Roman",
            "requestDate": str(datetime.datetime.now(localtz))
        })

    @pytest.fixture
    def mongo_db(self):
        yield MongoDB()

    @pytest.fixture
    def client_mock(self):
        yield mongomock.MongoClient()

    @pytest.fixture
    def mock_db(self, client_mock):
        yield client_mock.db

    def test_ingest_one(self, mock_db,  mongo_db, client):
        id_client = mongo_db.ingest_one(client.document, mock_db.collection.name, mock_db.name)
        stored_obj = mongo_db.find({'_id': id_client}, mock_db.collection.name, mock_db.name)

        assert [obj for obj in stored_obj if str(obj['_id']) == str(id_client)]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM