英文:
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)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论