0

I try to mock my Mongo database on tests. I find article which I follow, but unfortunately my tests write to real mongo database instead of mocked. I have database.py file with PyMongo creation:

from flask_pymongo import PyMongo

mongo = PyMongo()

I import mongo variable in __init__.py file to initialize with app:

import app.database as mongo_database


def create_app(env=None):
    app = Flask(__name__)
    ...
    app.config.from_object(config())
    mongo_database.mongo.init_app(app)

I use custom Mongo class to find data and insert to mongo, this is example of my controller:

@bp.route('/some-route', methods=['get'])
@jwt_required
def fetch_data():
    ...
    cached_data = MongoCache.getInstance().get_data(lender_id, "lenders")
    if cached_data:
        return cached_data
    ...
    MongoCache.getInstance().insert_data(lender_id, data, 'lenders')
    return data

And this is my MongoCache class:

import app.database


@Singleton
class MongoCache:
    def __init__(self):
        self.db = app.database.mongo.db

    ...

    def get_data(self, params, collection):
        ...
        result = self.db[collection].find_one(params)
        ...
        return result

    def insert_data(self, params, response, collection):
        ...
        try:
            self.db[collection].insert_one(data)
        except Exception as e:
            logger.exception(str(e))
            raise Exception(e)

But when I add patched PyMongo client, it does not work for me: tests.py

from mongomock import MongoClient

class PyMongoMock(MongoClient):
    def init_app(self, app):
        return super().__init__()

class MyTest(unittest.TestCase):

        def setUp(self):
        if os.environ.get('FLASK_ENV') != 'testing':
            raise Exception('Cannot run tests in non-test environment (FLASK_ENV must be set to "testing")')
        app = create_app()
        self.test_client = app.test_client()
        self._ctx = app.app_context()
        self._ctx.push()

        database_uri = self.test_client.application.config['SQLALCHEMY_DATABASE_URI']
        ...

    def test_actovia_lender_lookup(self):
        with patch('third_party_api', return_value={}) as patched_api:
            with patch("app.database", "mongo", PyMongoMock()):
                resp = self.test_client.get('/my-custom-url', headers={
                    'Authorization': 'Bearer %s' % jwt['access_token']
                })

                self.assertEqual(resp.status_code, 200)
                patched_api.assert_called_with('1')

Does anyone have any suggestion what I am doing wrong, and how can I fix that?

Vladyslav
  • 2,018
  • 4
  • 18
  • 44
  • you are not patching correctly. you should be patching in the `__init__` file, specifically, the `mongo_database` variable – gold_cy Sep 07 '20 at 12:27
  • @gold_cy, How I can patch in `__init__` file, if I use `with patch...` in `create_app` function how this should work? – Vladyslav Sep 07 '20 at 12:30
  • it works exactly the same way as it does for patching any other file, you need to provide the full path to the `__init__` file. you currently think you are patching something but in reality you are not – gold_cy Sep 07 '20 at 12:35

0 Answers0