首页 > 解决方案 > 使用 flask 和 mockupdb (mongodb) 测试 datetime 对象

问题描述

我正在使用 mockupdb 模块使用 Flask 的 REST 服务器(和 flask-pymongo)测试 MongoDB 作为 DB。我想在 json 请求中接收 DateTime,并将其存储为 Date 对象,以便将来使用此字段执行一些范围查询,因此,我将数据作为 EJSON (BSON) 发送,以保持数据与我完全相同。

这是测试用例:

@pytest.fixture()
def client_and_mongoserver():
    random.seed()
    mongo_server = MockupDB(auto_ismaster=True, verbose=True)
    mongo_server.run()
    config = Config()
    config.MONGO_URI = mongo_server.uri + '/test'
    flask_app = create_app(config)
    flask_app.testing = True
    client = flask_app.test_client()
    yield client, mongo_server
    mongo_server.stop()

def test_insert(client_and_mongoserver):
    client, server = client_and_mongoserver
    headers = [('Content-Type', 'application/json')]

    id = str(uuid.uuid4()).encode('utf-8')[:12]
    now = datetime.now()
    obj_id = ObjectId(id)
    toInsert = {
        "_id": obj_id,
        "datetime": now

    }
    toVerify = {
        "_id": obj_id,
        "datetime": now
    }

    future = go(client.post, '/api/insert', data=dumps(toInsert), headers=headers)
    request = server.receives(
        OpMsg({
            'insert': 'test',
            'ordered': True,
            '$db': "test",
            '$readPreference': {"mode": "primary"},
            'documents': [
                toVerify
            ]
        }, namespace='test')
    )
    request.ok(cursor={'inserted_id': id})
    # act
    http_response = future()

    # assert
    data = http_response.get_data(as_text=True)

这是终点。在插入调用之前,我将日期时间字符串转换为日期时间对象:

from flask_restful import Resource
from bson import json_util
class Insert(Resource):    
    def post(self):
        if not request.json:
            abort(400)
        json_data = json_util.loads(request.data)
        result = mongo.db.test.insert_one(json_data)
        return {'message': 'OK'}, 200

但是测试生成了这个断言:

self = MockupDB(localhost, 37213)
args = (OpMsg({"insert": "test", "ordered": true, "$db": "test", "$readPreference": {"mode": "primary"}, "documents": [{"_id": {"$oid": "63343264363661622d393764"}, "datetime": {"$date": 1543493218306}}]}, namespace="test"),)
kwargs = {}, timeout = 10, end = 1543504028.309115
matcher = Matcher(OpMsg({"insert": "test", "ordered": true, "$db": "test", "$readPreference": {"mode": "primary"}, "documents": [{"_id": {"$oid": "63343264363661622d393764"}, "datetime": {"$date": 1543493218306}}]}, namespace="test"))
request = OpMsg({"insert": "test", "ordered": true, "$db": "test", "$readPreference": {"mode": "primary"}, "documents": [{"_id": {"$oid": "63343264363661622d393764"}, "datetime": {"$date": 1543493218306}}]}, namespace="test")

def receives(self, *args, **kwargs):
    """Pop the next `Request` and assert it matches.

    Returns None if the server is stopped.

    Pass a `Request` or request pattern to specify what client request to
    expect. See the tutorial for examples. Pass ``timeout`` as a keyword
    argument to override this server's ``request_timeout``.
    """
    timeout = kwargs.pop('timeout', self._request_timeout)
    end = time.time() + timeout
    matcher = Matcher(*args, **kwargs)
    while not self._stopped:
        try:
            # Short timeout so we notice if the server is stopped.
            request = self._request_q.get(timeout=0.05)
        except Empty:
            if time.time() > end:
                raise AssertionError('expected to receive %r, got nothing' % matcher.prototype)
        else:
            if matcher.matches(request):
                return request
            else:
                raise AssertionError('expected to receive %r, got %r'
>                                        % (matcher.prototype, request))
E                   AssertionError: expected to receive OpMsg({"insert": "test", "ordered": true, "$db": "test", "$readPreference": {"mode": "primary"}, "documents": [{"_id": {"$oid": "63343264363661622d393764"}, "datetime": {"$date": 1543493218306}}]}, namespace="test"), got OpMsg({"insert": "test", "ordered": true, "$db": "test", "$readPreference": {"mode": "primary"}, "documents": [{"_id": {"$oid": "63343264363661622d393764"}, "datetime": {"$date": 1543493218306}}]}, namespace="test")

.venv/lib/python3.6/site-packages/mockupdb/__init__.py:1291: AssertionError

值匹配,但断言以任何一种方式提出。如何使用烧瓶测试 Date 对象?

编辑:正如@bauman.space 所指出的。缺乏:

'$db': 'test',  # this key appears somewhere at the driver 
'$readPreference': {"mode": "primary"},  # so does this one

不要影响 mockupdb 所做的验证。我已经在其他测试用例中测试过了。

编辑2:更改问题以防止混淆

标签: flaskpymongo

解决方案


你的断言很有描述性

AssertionError: 
expected to receive 
OpMsg(
    {"insert": "test", 
     "ordered": true, 
     "documents": [{"_id": "a3dbe8a7e1cc43469b706a8877b0a14a", 
                    "datetime": {"$date": 1542901445120}}]
     }, namespace="test"
), 
got 
OpMsg(
    {"insert": "test", 
     "ordered": true, 
     "$db": "test", 
     "$readPreference": {"mode": "primary"}, 
     "documents": [{"_id": "a3dbe8a7e1cc43469b706a8877b0a14a", 
                    "datetime": {"$date": 1542901445120}}]
    }, namespace="test")

看起来您只需要在验证码中包含一些标准的 MongoDB 密钥。

用这个换掉你的,试试看?

request = server.receives(
    OpMsg({
        'insert': 'test',
        'ordered': True,
        '$db': 'test',  # this key appears somewhere at the driver 
        '$readPreference': {"mode": "primary"},  # so does this one
        'documents': [
            toVerify
        ]
    }, namespace='test')
)

推荐阅读