skip to Main Content

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="[email protected]"

    # 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?

2

Answers


  1. Chosen as BEST ANSWER

    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": "[email protected]",
                "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("[email protected]")
            self.assertIsNone(user_ko)
    

  2. 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

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search