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

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

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

问题

以下是您要翻译的内容:

  1. 我有一个使用Mongo数据库的FastAPI
  2. 我尝试为一些需要Mongo连接的函数编写测试
  3. 这是我的用户集合和其字段:
  4. from mongoengine import Document, EmailField, StringField, EnumField
  5. class User(Document):
  6. meta = {"collection": "users"}
  7. email = EmailField(unique=True)
  8. hashed_password = StringField()
  9. role = EnumField(UserRole)
  10. def username(self):
  11. return self.email.split('@')[0]
  12. def __str__(self):
  13. return f'{self.email} ({self.role})'
  14. 这是我的函数:
  15. class UserService:
  16. @staticmethod
  17. def existing_user(email: str) -> Optional[User]:
  18. try:
  19. user = User.objects(email=email).first()
  20. except ServerSelectionTimeoutError as e:
  21. raise e
  22. return user
  23. 请问如何最好地测试这个函数(使用pytest)?我想要模拟我的MongoDB,但我无法使用mongomock或直接使用monkeypatch来实现
  24. 非常感谢
  25. 我的测试文件
  26. from domain.entities.user import UserRole, User
  27. from mongomock import MongoClient
  28. class TestUserServiceMethods:
  29. email="john@doe.fr"
  30. # 用户示例
  31. user = User(email=email,
  32. role=UserRole.admin,
  33. hashed_password="hashed_pwd")
  34. add_user = {
  35. "email": email,
  36. "role": UserRole.admin,
  37. "hashed_password": "hashed_pwd"
  38. }
  39. user_service = UserService()
  40. client = MongoClient()
  41. mock_db = client['ml-db']
  42. user_collection = mock_db['users']
  43. user_collection.insert_one(add_user)
  44. def test_existing_user(self, monkeypatch):
  45. with monkeypatch.context() as m:
  46. m.setattr('pymongo.MongoClient', lambda *args, **kwargs: self.client)
  47. result = self.user_service.existing_user(self.email)
  48. assert result == self.user
  49. 似乎模拟没有成功,因为我得到了以下错误:
  50. mongoengine.connection.ConnectionFailure: 未定义默认连接
  51. 我应该直接使用FastAPItest_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:

  1. from mongoengine import Document, EmailField, StringField, EnumField
  2. class User(Document):
  3. meta = {"collection": "users"}
  4. email = EmailField(unique=True)
  5. hashed_password = StringField()
  6. role = EnumField(UserRole)
  7. def username(self):
  8. return self.email.split('@')[0]
  9. def __str__(self):
  10. return f'{self.email} ({self.role})

Here my function

  1. class UserService:
  2. @staticmethod
  3. def existing_user(email: str) -> Optional[User]:
  4. try:
  5. user = User.objects(email=email).first()
  6. except ServerSelectionTimeoutError as e:
  7. raise e
  8. 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

  1. from domain.entities.user import UserRole, User
  2. from mongomock import MongoClient
  3. class TestUserServiceMethods:
  4. email="john@doe.fr"
  5. # User example
  6. user = User(email=email,
  7. role=UserRole.admin,
  8. hashed_password="hashed_pwd")
  9. add_user = {
  10. "email": email,
  11. "role": UserRole.admin,
  12. "hashed_password": "hashed_pwd"
  13. }
  14. user_service = UserService()
  15. client = MongoClient()
  16. mock_db = client['ml-db']
  17. user_collection = mock_db['users']
  18. user_collection.insert_one(add_user)
  19. def test_existing_user(self, monkeypatch):
  20. with monkeypatch.context() as m:
  21. m.setattr('pymongo.MongoClient', lambda *args, **kwargs: self.client)
  22. result = self.user_service.existing_user(self.email)
  23. assert result == self.user

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

  1. 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。

例如:

  1. from mongoengine import connect
  2. 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 :

  1. from mongoengine import connect
  2. 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:

  1. **更新** 正如Ozs所说最好的方法是创建一个虚拟数据库在最后将其删除下面是解决我的问题的示例
  2. ```python
  3. from unittest import TestCase
  4. from mongoengine import connect
  5. import UserService, password_context
  6. import UserRole, User
  7. class TestUserServiceMethods(TestCase):
  8. @classmethod
  9. def setUpClass(cls):
  10. cls.connection = connect('mongoenginetest', host='mongomock://localhost/ml-db')
  11. def setUp(cls):
  12. cls.data = {
  13. "id": "6499594c58ebb74dd4985e59",
  14. "email": "mail@test.fr",
  15. "pwd": "test",
  16. "hashed_pwd": password_context.hash("test"),
  17. "role": UserRole.admin
  18. }
  19. cls.doc = {
  20. "email": cls.data['email'],
  21. "role": cls.data['role'],
  22. "hashed_password": cls.data['hashed_pwd']
  23. }
  24. cls.user = User(
  25. email=cls.data['email'],
  26. role=cls.data['role'],
  27. hashed_password=cls.data['hashed_pwd'])
  28. cls.user_service = UserService()
  29. cls.user.save()
  30. @classmethod
  31. def tearDownClass(cls):
  32. cls.connection.drop_database('mongoenginetest')
  33. def test_existing_user(self):
  34. user = self.user_service.existing_user(self.data['email'])
  35. self.assertIsNotNone(user)
  36. user_ko = self.user_service.existing_user("error@mail.fr")
  37. 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

  1. from unittest import TestCase
  2. from mongoengine import connect
  3. import UserService, password_context
  4. import UserRole, User
  5. class TestUserServiceMethods(TestCase):
  6. @classmethod
  7. def setUpClass(cls):
  8. cls.connection = connect('mongoenginetest', host='mongomock://localhost/ml-db')
  9. def setUp(cls):
  10. cls.data = {
  11. "id": "6499594c58ebb74dd4985e59",
  12. "email": "mail@test.fr",
  13. "pwd": "test",
  14. "hashed_pwd": password_context.hash("test"),
  15. "role": UserRole.admin
  16. }
  17. cls.doc = {
  18. "email": cls.data['email'],
  19. "role": cls.data['role'],
  20. "hashed_password": cls.data['hashed_pwd']
  21. }
  22. cls.user = User(
  23. email=cls.data['email'],
  24. role=cls.data['role'],
  25. hashed_password=cls.data['hashed_pwd'])
  26. cls.user_service = UserService()
  27. cls.user.save()
  28. @classmethod
  29. def tearDownClass(cls):
  30. cls.connection.drop_database('mongoenginetest')
  31. def test_existing_user(self):
  32. user = self.user_service.existing_user(self.data['email'])
  33. self.assertIsNotNone(user)
  34. user_ko = self.user_service.existing_user("error@mail.fr")
  35. 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:

确定