mongomock
mongomock copied to clipboard
TypeError: CodecOptions got an unexpected keyword argument
The following exception is raised when using pymongo 4.3.2 but it worked for pymongo 4.2:
TypeError: __new__() got an unexpected keyword argument 'datetime_conversion'
With the following code snippet (pymongo 4.3.2, mongomock 4.1.2):
import mongomock
from bson import CodecOptions
client = mongomock.MongoClient()
database = client.get_database("db").get_collection("c").with_options(codec_options=CodecOptions(tz_aware=True))
database
Having same issue. pymongo added an extra parameter to their CodecOptions (see release notes https://pymongo.readthedocs.io/en/stable/changelog.html#changes-in-version-4-3-4-3-2). mongomock will need to update their CodecOptions class to match.
What I did as a workaround was actually patch my import of CodecOptions to use mongomock's CodecOptions for my tests.
So something like:
# TEMP - hack/workaround for https://github.com/mongomock/mongomock/issues/810
from mongomock.codec_options import CodecOptions as MockCodecOptions
mocker.patch("my.module_i_am_testing.CodecOptions", MockCodecOptions)
That way mongomock is happy so long as we don't use the new CodecOptions
in pymongo.
@tkutcher , could you please share example of a code, how do you mock mongomock?
@arturmkr Sure - here is a bit more context:
Let's say in my_lib/my_module.py
I have something like:
import pymongo
from bson.codec_options import CodecOptions
def get_mongo_client(db_uri):
return pymongo.MongoClient(db_uri)
def get_collection(mongo, name):
return mongo["main"].get_collection(name, codec_options=CodecOptions(tz_aware=True))
Then, in my root conftest.py
file:
@pytest.fixture(autouse=True)
def _mock_mongo_client(mocker) -> None:
# Don't make any real connections to mongo, instead use mongomock.MongoClient.
mocker.patch("my_lib.my_module.pymongo.MongoClient", mongomock.MongoClient)
# Mock the CodecOptions import to be the ones mongomock is expecting.
from mongomock.codec_options import CodecOptions as MockCodecOptions
mocker.patch("my_lib.my_module.CodecOptions", MockCodecOptions)
So, in a test:
from my_lib.my_module import get_mongo_client, get_collection
def test_foo():
mongo = get_mongo_client("foo") # gets a mongomock.MongoClient instead of pymongo.MongoClient
collection = mongo.get_collection(mongo, "blah") # uses mongomock CodecOptions instead of bson.codec_options.
And the exact same code outside of the testing environment uses the real connections with pymongo.
@tkutcher , Thank you so much!
I also encountered this but resolved it the opposite way - by patching mongomock
to use the real CodecOptions
type, instead of patching my code. Not sure it's better, but it might also help someone.
This pytest fixture should do it:
from unittest import patch
import mongomock.codec_options
from bson import CodecOptions
@pytest.fixture
def patch_mongomock_codecopts(self):
with patch.object(mongomock.codec_options, "CodecOptions", CodecOptions):
yield