如何在Python中对使用mongoengine连接的函数进行测试?

huangapple go评论73阅读模式
英文:

How to realize tests on functions which are using mongoengine connection in Python?

问题

以下是您要翻译的内容:

我有一个使用Mongo数据库的FastAPI
我尝试为一些需要Mongo连接的函数编写测试
这是我的用户集合和其字段:

from mongoengine import Document, EmailField, StringField, EnumField 
class User(Document):  
    meta = {"collection": "users"}
    email = EmailField(unique=True)
    hashed_password = StringField()
    role = EnumField(UserRole)

    def username(self):
        return self.email.split('@')[0]

    def __str__(self):
        return f'{self.email} ({self.role})'

这是我的函数:

class UserService:

    @staticmethod
    def existing_user(email: str) -> Optional[User]:


        try:
             user = User.objects(email=email).first()
        except ServerSelectionTimeoutError as e:
            raise e

        return user

请问如何最好地测试这个函数(使用pytest)?我想要模拟我的MongoDB,但我无法使用mongomock或直接使用monkeypatch来实现

非常感谢

我的测试文件

 from domain.entities.user import UserRole, User
 from mongomock import MongoClient
 class TestUserServiceMethods:

    email="john@doe.fr"

    # 用户示例
    user = User(email=email,
                  role=UserRole.admin,
                  hashed_password="hashed_pwd")

    add_user = {
      "email": email,
      "role": UserRole.admin,
      "hashed_password": "hashed_pwd"
    }

    

    user_service = UserService()

    client = MongoClient()

    mock_db = client['ml-db']
    user_collection = mock_db['users']
    user_collection.insert_one(add_user)



    def test_existing_user(self, monkeypatch):
        with monkeypatch.context() as m:
            m.setattr('pymongo.MongoClient', lambda *args, **kwargs: self.client)

            result = self.user_service.existing_user(self.email)

             assert result == self.user

似乎模拟没有成功,因为我得到了以下错误:

mongoengine.connection.ConnectionFailure: 未定义默认连接

我应该直接使用FastAPI的test_client吗?
英文:

I have Fast API with a Mongo Database
I try to realize my tests for some functions which need mongo connection
Here my collection users and its fields:

from mongoengine import Document, EmailField, StringField, EnumField 
class User(Document):  
    meta = {"collection": "users"}
    email = EmailField(unique=True)
    hashed_password = StringField()
    role = EnumField(UserRole)

    def username(self):
        return self.email.split('@')[0]

    def __str__(self):
        return f'{self.email} ({self.role})

Here my function

class UserService:

    @staticmethod
    def existing_user(email: str) -> Optional[User]:


        try:
             user = User.objects(email=email).first()
        except ServerSelectionTimeoutError as e:
            raise e

        return user

What is the best way to test this function please (using pytest)? I would like to mock my MongoDB but I didn't manage with mongomock or directly with monkeypatch

Thank you very much

My test file

 from domain.entities.user import UserRole, User
 from mongomock import MongoClient
 class TestUserServiceMethods:

    email="john@doe.fr"

    # User example
    user = User(email=email,
                  role=UserRole.admin,
                  hashed_password="hashed_pwd")

    add_user = {
      "email": email,
      "role": UserRole.admin,
      "hashed_password": "hashed_pwd"
    }

    

    user_service = UserService()

    client = MongoClient()

    mock_db = client['ml-db']
    user_collection = mock_db['users']
    user_collection.insert_one(add_user)



    def test_existing_user(self, monkeypatch):
        with monkeypatch.context() as m:
            m.setattr('pymongo.MongoClient', lambda *args, **kwargs: self.client)

            result = self.user_service.existing_user(self.email)

             assert result == self.user

It seems the mock didn't sucess because I got as error :

mongoengine.connection.ConnectionFailure: You have not defined a default connection

Should I use directly Fast app with test_client?

答案1

得分: 0

你需要在执行任何操作之前,从mogoengine运行connect方法,使用db_name(默认别名为"default")和connection_string。

例如:

from mongoengine import connect

connect("db_name", host="connection_string", mongo_client_class=client)

代码中的client将来自monfoengine,而在测试中将来自mongomock。

英文:

You need to run connect method from mogoengine with db_name (default alias is "default") and connection_string before any action you do.

for example :

from mongoengine import connect

connect("db_name", host="connection_string", mongo_client_class=client)

the client in the code would be from monfoengine and in tests it would be from mongomock

答案2

得分: 0

Here is the translated code:

**更新** 正如Ozs所说最好的方法是创建一个虚拟数据库在最后将其删除下面是解决我的问题的示例

```python
from unittest import TestCase
from mongoengine import connect
import UserService, password_context 
import UserRole, User

class TestUserServiceMethods(TestCase):

    @classmethod
    def setUpClass(cls):
        cls.connection = connect('mongoenginetest', host='mongomock://localhost/ml-db')

    def setUp(cls):
        cls.data = {
            "id": "6499594c58ebb74dd4985e59",
            "email": "mail@test.fr",
            "pwd": "test",
            "hashed_pwd": password_context.hash("test"),
            "role": UserRole.admin
        }

        cls.doc = {
            "email": cls.data['email'],
            "role": cls.data['role'],
            "hashed_password": cls.data['hashed_pwd']
        }

        cls.user = User(
            email=cls.data['email'],
            role=cls.data['role'],
            hashed_password=cls.data['hashed_pwd'])

        cls.user_service = UserService()

        cls.user.save()

    @classmethod
    def tearDownClass(cls):
        cls.connection.drop_database('mongoenginetest')

    def test_existing_user(self):
        user = self.user_service.existing_user(self.data['email'])
        self.assertIsNotNone(user)

        user_ko = self.user_service.existing_user("error@mail.fr")
        self.assertIsNone(user_ko)

Please note that I've translated the code, but I haven't included the comments as they appear to be in English and don't require translation.

英文:

UPDATE As Ozs said, the best way is to create a Fake database and to drop it at the end. Here an example which resolves my problem

from unittest import TestCase

from mongoengine import connect

import UserService, password_context 
import UserRole, User


class TestUserServiceMethods(TestCase):

    @classmethod
    def setUpClass(cls):
        cls.connection = connect('mongoenginetest', host='mongomock://localhost/ml-db')

    def setUp(cls):
        cls.data = {
            "id": "6499594c58ebb74dd4985e59",
            "email": "mail@test.fr",
            "pwd": "test",
            "hashed_pwd": password_context.hash("test"),
            "role": UserRole.admin
        }

        cls.doc = {
            "email": cls.data['email'],
            "role": cls.data['role'],
            "hashed_password": cls.data['hashed_pwd']
        }
      

        cls.user = User(
            email=cls.data['email'],
            role=cls.data['role'],
            hashed_password=cls.data['hashed_pwd'])

        cls.user_service = UserService()

        cls.user.save()

    @classmethod
    def tearDownClass(cls):
        cls.connection.drop_database('mongoenginetest')

    def test_existing_user(self):
        user = self.user_service.existing_user(self.data['email'])
        self.assertIsNotNone(user)

        user_ko = self.user_service.existing_user("error@mail.fr")
        self.assertIsNone(user_ko)

huangapple
  • 本文由 发表于 2023年6月27日 20:24:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/76564826.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定