파이썬 유닛 테스트를 위해 mongodb를 조롱하는 방법은 무엇입니까?
사용 중mockPython 2.7을 위한 모듈은 나의 다른 기능들을 조롱하고 사용합니다.
unittest쓰기 단위 테스트용입니다.
MongoDB를 조롱하는 것과 모의 기능을 사용하는 것이 다른지 궁금합니다(mock.patch호출되는 함수?)아니면 다른 패키지를 사용해야 합니까?
테스트 mongodb 인스턴스를 실행하고 싶지 않습니다.내가 원하는 것은 약간의 템포 데이터와 전화를 할 수 있는 것입니다.pymongo기능성나는 단지 모듈에 대한 모의 글을 쓰는 방법이 있을까 하는 생각에 약간 빠져 있습니다(예를 들어.pymongo) 또는 모든 것이 가능합니다.mock모듈.
이에 대한 예나 튜토리얼을 제공해 주시면 감사하겠습니다.
테스트할 코드
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)
이것을 테스트하기 위해, 저는 테스트 몽고드브가 가동되고 실행되는 것을 별로 원하지 않습니다!또한, 제가 저장한 데이터를 실제로 검색하여 DB에 있는지 확인하고 싶기 때문에 db.userssave 및 db.users.find를 모의하고 싶지 않습니다.제 기억 속에 있는 모델별로 고정장치를 만들어 작업해야 할 것 같습니다.외부 도구만 있으면 됩니까?
이런 가짜 자료를 보관하려고 하는데, 어떻게 처리해야 할지 모르겠어요.
users = {
{'name' : 'Kelly', 'email' : 'kelly@gmail.com'},
{'name': 'Sam', 'email': 'sam@gmail.com'}
}
저는 몽고드를 조롱하기 위해 몽고드를 사용하는 것을 추천합니다.이것은 기본적으로 파이몬고 인터페이스를 가진 메모리 내 몽고드b이며 특별히 이 목적을 위해 만들어졌습니다.
https://github.com/mongomock/mongomock
필드별로 검색할 필요가 없는 단순한 작업을 수행하는 경우에도 이 작업을 수행할 수 있습니다.
@mock.patch("pymongo.collection.Collection.find")
def test_name(self, mock_find):
mock_find.return_value = {'name' : 'Kelly', 'email' : 'kelly@gmail.com'}
# rest of test
물론 PyMongo를 조롱할 수 있지만, MongoDB 서버 자체를 조롱하는 것을 추천합니다.MongoDB를 위한 순수 파이썬 에뮬레이터를 작성했습니다. MongoDB Wire Protocol 메시지에 완전히 제어할 수 있습니다. 어떤 방법을 선택하든 다음과 같습니다.
http://mockupdb.readthedocs.io/tutorial.html
다음은 Mockup을 사용하는 예입니다.Python 애플리케이션이 있는 DB:
https://emptysqua.re/blog/test-mongodb-failures-mockupdb/
MongoDB 와이어 프로토콜에 대한 깊은 지식이 필요하지만, 어쨌든 그것은 습득하기에 유용한 기술입니다.
@mirthbottle 답변에 추가하여 mongo 객체의 속성을 필드로 액세스하려면 다음과 같이 할 수 있습니다.
class MongoDummybject:
def __init__(self, _data):
for _d in _data:
setattr(self, _d, _data[_d])
return_data = {'name' : 'Nishant', 'email' : 'nishant@gmail.com'}
@mock.patch("pymongo.collection.Collection.find")
def test_name(self, mock_find):
mock_find.return_value = MongoDummybject(return_data)
사용자 지정 예외로 묶인 장치 테스트 예외의 경우 mongomock 컬렉션 내의 패치 함수(예: bulk_write)
@mock.patch("mongomock.collection.Collection.bulk_write", side_effect=BulkWriteError({}))
def test_bulk_wrt_err(self, blk_wrt_err):
with self.assertRaises(SpecialBulkWriteExcep) as context:
add_user()
샘플 코드:
Mongomock은 테스트에 권장되는 방법입니다. 시작하기 위한 실행 가능한 예는 다음과 같습니다.
client.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.파이의
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
@funnydman의 예를 사용합니다.
client.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.파이의
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)]
이 질문에 대한 가능한 대답으로 파이테스트모크 리소스에 대해 언급하고 싶은 사람이 있습니까?
개발 상자에 있는 도커에 따라 다르지만, 매번 컨테이너를 회전시킨다고 해서 속도가 느려질까 봐 걱정입니다.
저는 도커가 상태 저장을 허용한다고 생각하지만, 그것은 유닛 테스트의 dao를 위반하고, 테스트는 독립적이어야 하며 외부 자원에 의존하지 않아야 한다는 것입니다(가능하다면 도커도).
댓글은 환영합니다.
언급URL : https://stackoverflow.com/questions/42239241/how-to-mock-mongodb-for-python-unittests
'programing' 카테고리의 다른 글
| 유형 스크립트의 대응 이벤트 유형 (0) | 2023.07.10 |
|---|---|
| null 값을 바꾸는 동안 두 행을 하나로 병합 (0) | 2023.07.10 |
| Oracle Database에서 SQL을 사용하여 XML Clob에서 데이터 추출 (0) | 2023.07.10 |
| ORA-02287: 시퀀스 번호는 여기에서 허용되지 않습니다. (0) | 2023.07.10 |
| 스프링 부츠 & JPA:선택적이고 범위가 넓은 기준으로 검색 쿼리 구현 (0) | 2023.07.10 |