I need help while mocking mongodb. I am using mongomock to mock mongodb.
My project structure is:
-- my_mongo.py
-- code.py
-- my_test.py
my_mongo.py has :
from pymongo import MongoClient
def get_db():
client = MongoClient(os.environ['MONGODB_URI'])
db = client['my_db']
return db
def insert(id, data):
return get_db().results.insert_one(
{
"id": id,
"data":df.to_json(),
}).id
and code.py has
import my_mongo
def action():
#do somethings
my_mongo.insert(id, data)
and my_test.py has
import mongomock
import my_mongo
from unittest import mock
with patch.object(my_mongo.get_db().client, "client", mongomock.MongoClient()):
import code
def test_action_1():
my_mongo.insert = mock.Mock(return_value=1)
code.action()
def test_action_2():
with patch.object(my_mongo.get_db(), "get_db", mongomock.MongoClient().db):
code.action()
It throws pymongo.errors.ServerSelectionTimeoutError for both tests. So, It still goes into the insert_one() method in my_mongo.py. I expect in test_action_1 my_mongo.insert returns 1, but it doesn't.
What am I missing?
I'm not entirely sure what
mongomockis for, but it looks like it's for mocking an entire mongo database and not actually using python mocking. I'm going to answer without includingmongomocksince I don't think you really need it, so you can take that for what it's worth.There were a few issues:
Calling
patch.objectwill patch the given method on whatever object you give it. If you callget_dbin the test, thencode.actioncallsget_db, those are 2 different objects. Maybe this works? But I'm skeptical, so I just changed it.Don't use
codeas your module name. That's already a module included with python.code.actionwas missing args and a return statement.You'll also notice that I changed how and what was being mocked to illustrate different ways to accomplish the mocking. Test 1 mocks the
insertcall with a function decorator. Test 2 mocks theget_dbcall with acontextmanager. Either is correct, just showing that you have options.Here's the finished product:
my_mongo.py:
my_code.py:
my_test.py