Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

issue with matcher #13

Closed
karpikpl opened this issue Feb 24, 2018 · 4 comments
Closed

issue with matcher #13

karpikpl opened this issue Feb 24, 2018 · 4 comments

Comments

@karpikpl
Copy link

Hi,
thanks for building the library!
I've run into interesting issue:
AssertionError: expected to receive Command({"find": "dataSources", "filter": {"_id": {"$oid": "5a8f1e368f7936badfbb0cfa"}}, "limit": 1, "singleBatch": true}, flags=SlaveOkay, namespace="app"), got Command({"find": "dataSources", "filter": {"_id": {"$oid": "5a8f1e368f7936badfbb0cfa"}}, "limit": 1, "singleBatch": true}, flags=SlaveOkay, namespace="app")

As far as I can tell, those two are identical :/
Do you know what might be the reason for AssertionError?

@ajdavis
Copy link
Collaborator

ajdavis commented Feb 24, 2018

They do look identical. Can you share some code with me that reproduces the error?

@karpikpl
Copy link
Author

karpikpl commented Feb 24, 2018

hey,
thanks for quick reply.
Here's my flask route handler (and this is my first python app):

from app import app, getMongo
from tools import JSONEncoder
from flask import jsonify, abort
from bson.objectid import ObjectId
#from app.mongo import dataProvider
# todo: switch to async await ? https://github.com/xzased/pytest-async-mongodb


@app.route('/dataSource/<string:id>')
def getDataSource(id):
    if not id:
        abort(404)

    source = getMongo().db.dataSources.find_one_or_404(ObjectId(id))

    return JSONEncoder.JSONEncoder().encode(source)

and here's the test

import unittest
import os

from app import app, getMongo
from mockupdb import MockupDB, go, Command
from pymongo import MongoClient


class GetDataSourceTestCase(unittest.TestCase):

    def setUp(self):
        self.server = MockupDB(auto_ismaster=True, verbose=True)
        self.server.run()
        # create mongo connection to mock server
        print('calling getMongo with ' + self.server.uri)
        client = getMongo(self.server.uri)

        app.testing = True
        self.app = app.test_client()

    def tearDown(self):
        self.server.stop()

    def test_getDataSource(self):
        future = go(self.app.get, '/dataSource/5a8f1e368f7936badfbb0cfa')
        request = self.server.receives(
            Command({"find": "dataSources", "filter": {"_id": {"$oid": "5a8f1e368f7936badfbb0cfa"}}, "limit": 1, "singleBatch": True}, flags=4, namespace="app"))

        request.ok()
        http_response = future()

        self.assertEqual("ok", http_response.get_data(as_text=True))

logs

====================================================== FAILURES ======================================================
______________________________________ GetDataSourceTestCase.test_getDataSource ______________________________________

self = <tests.getDataSource_test.GetDataSourceTestCase testMethod=test_getDataSource>

    def test_getDataSource(self):
        future = go(self.app.get, '/dataSource/5a8f1e368f7936badfbb0cfa')
        request = self.server.receives(
>           Command({"find": "dataSources", "filter": {"_id": {"$oid": "5a8f1e368f7936badfbb0cfa"}}, "limit": 1, "singleBatch": True}, flags=4, namespace="app"))

tests/getDataSource_test.py:27:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = MockupDB(localhost, 49407)
args = (Command({"find": "dataSources", "filter": {"_id": {"$oid": "5a8f1e368f7936badfbb0cfa"}}, "limit": 1, "singleBatch": true}, flags=SlaveOkay, namespace="app"),)
kwargs = {}, timeout = 10, end = 1519483250.434251
matcher = Matcher(Command({"find": "dataSources", "filter": {"_id": {"$oid": "5a8f1e368f7936badfbb0cfa"}}, "limit": 1, "singleBatch": true}, flags=SlaveOkay, namespace="app"))
request = Command({"find": "dataSources", "filter": {"_id": {"$oid": "5a8f1e368f7936badfbb0cfa"}}, "limit": 1, "singleBatch": true}, flags=SlaveOkay, namespace="app")

    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 Command({"find": "dataSources", "filter": {"_id": {"$oid": "5a8f1e368f7936badfbb0cfa"}}, "limit": 1, "singleBatch": true}, flags=SlaveOkay, namespace="app"), got Command({"find": "dataSources", "filter": {"_id": {"$oid": "5a8f1e368f7936badfbb0cfa"}}, "limit": 1, "singleBatch": true}, flags=SlaveOkay, namespace="app")

venv/lib/python3.6/site-packages/mockupdb/__init__.py:1095: AssertionError
========================================= 1 failed, 6 passed in 1.48 seconds =========================================

@ajdavis
Copy link
Collaborator

ajdavis commented Feb 24, 2018

Thanks, that's very helpful.

The problem is you're using the JSON representation of ObjectId, more or less, to specify your matcher, rather than an actual ObjectId instance. This appears like it should work but it doesn't:

{"_id": {"$oid": "5a8f1e368f7936badfbb0cfa"}}

Instead, you want an actual ObjectId instance:

ObjectId('5a8f1e368f7936badfbb0cfa')

Now, for complicated reasons that are my fault, you need to import ObjectId from MockupDB instead of from PyMongo:

from mockupdb._bson import ObjectId as mockup_oid

Use that ObjectId in your matcher, and reply to the "find" command with a proper MongoDB "find" reply:

    request = self.server.receives(
            Command({"find": "dataSources", "filter": {"_id": mockup_oid('5a918f9fa08bff9c7688d3e1')}, "limit": 1, "singleBatch": True}, flags=4, namespace="app"))

    request.ok(cursor={'id': 0, 'firstBatch':[{'a': 2}]})

I'll fix MockupDB so you don't need the odd "import" hack to fix ObjectId comparisons.

@karpikpl
Copy link
Author

thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants