Security News
PyPI’s New Archival Feature Closes a Major Security Gap
PyPI now allows maintainers to archive projects, improving security and helping users make informed decisions about their dependencies.
.. image:: https://img.shields.io/pypi/v/mongomock.svg?style=flat-square :target: https://pypi.python.org/pypi/mongomock .. image:: https://img.shields.io/github/actions/workflow/status/mongomock/mongomock/lint-and-test.yml?branch=develop&style=flat-square :target: https://github.com/mongomock/mongomock/actions?query=workflow%3Alint-and-test .. image:: https://img.shields.io/pypi/l/mongomock.svg?style=flat-square :target: https://pypi.python.org/pypi/mongomock .. image:: https://img.shields.io/codecov/c/github/mongomock/mongomock.svg?style=flat-square :target: https://codecov.io/gh/mongomock/mongomock
Mongomock is a small library to help testing Python code that interacts with MongoDB via Pymongo.
To understand what it's useful for, we can take the following code:
.. code-block:: python
def increase_votes(collection): for document in collection.find(): collection.update_one(document, {'$set': {'votes': document['votes'] + 1}})
The above code can be tested in several ways:
Option number 1 is obviously the best approach here, since we are testing against a real mongodb instance. However, a mongodb instance needs to be set up for this, and cleaned before/after the test. You might want to run your tests in continuous integration servers, on your laptop, or other bizarre platforms - which makes the mongodb requirement a liability.
We are left with #2 and #3. Unfortunately they are very high maintenance in real scenarios, since they replicate the series of calls made in the code, violating the DRY rule. Let's see #2 in action - we might write our test like so:
.. code-block:: python
def test_increase_votes(): objects = [dict(...), dict(...), ...] collection_mock = my_favorite_mock_library.create_mock(Collection) record() collection_mock.find().AndReturn(objects) for obj in objects: collection_mock.update_one(obj, {'$set': {'votes': obj['votes']}}) replay() increase_votes(collection_mock) verify()
Let's assume the code changes one day, because the author just learned about the '$inc' instruction:
.. code-block:: python
def increase_votes(collection): collection.update_many({}, {'$inc': {'votes': 1}})
This breaks the test, although the end result being tested is just the same. The test also repeats large portions of the code we already wrote.
We are left, therefore, with option #3 -- you want something to behave like a mongodb database collection, without being one. This is exactly what this library aims to provide. With mongomock, the test simply becomes:
.. code-block:: python
def test_increase_votes(): collection = mongomock.MongoClient().db.collection objects = [dict(votes=1), dict(votes=2), ...] for obj in objects: obj['_id'] = collection.insert_one(obj).inserted_id increase_votes(collection) for obj in objects: stored_obj = collection.find_one({'_id': obj['_id']}) stored_obj['votes'] -= 1 assert stored_obj == obj # by comparing all fields we make sure only votes changed
This code checks increase_votes with respect to its functionality, not syntax or algorithm, and therefore is much more robust as a test.
If the code to be tested is creating the connection itself with pymongo, you can use
mongomock.patch (NOTE: you should use :code:pymongo.MongoClient(...)
rather than
:code:from pymongo import MongoClient
, as shown below):
.. code-block:: python
@mongomock.patch(servers=(('server.example.com', 27017),)) def test_increate_votes_endpoint(): objects = [dict(votes=1), dict(votes=2), ...] client = pymongo.MongoClient('server.example.com') client.db.collection.insert_many(objects) call_endpoint('/votes') ... verify client.db.collection
MongoDB is complex. This library aims at a reasonably complete mock of MongoDB for testing purposes, not a perfect replica. This means some features are not likely to make it in any time soon.
Also, since many corner cases are encountered along the way, our goal is to try and TDD our way into completeness. This means that every time we encounter a missing or broken (incompatible) feature, we write a test for it and fix it. There are probably lots of such issues hiding around lurking, so feel free to open issues and/or pull requests and help the project out!
NOTE: We don't include pymongo functionality as "stubs" or "placeholders". Since this library is
used to validate production code, it is unacceptable to behave differently than the real pymongo
implementation. In such cases it is better to throw NotImplementedError
than implement a modified
version of the original behavior.
The major version 4 of Pymongo changed the API quite a bit. The Mongomock library has evolved to help you ease the migration:
When submitting a PR, please make sure that:
examples in tests
_ for reference).To download, setup and perfom tests, run the following commands on Mac / Linux:
.. code-block:: console
$ git clone git@github.com:mongomock/mongomock.git $ pipx install hatch $ cd mongomock $ hatch test
Alternatively, docker-compose can be used to simplify dependency management for local development:
.. code-block:: console
$ git clone git@github.com:mongomock/mongomock.git $ cd mongomock $ docker compose build $ docker compose run --rm mongomock
If you want to run hatch
against a specific environment in the container:
.. code-block:: console
$ docker compose run --rm mongomock hatch test -py=3.11 -i pymongo=4
If you'd like to run only one test, you can also add the test name at the end of your command:
.. code-block:: console
$ docker compose run --rm mongomock hatch test -py=3.12 -i pymongo=4 tests/test__mongomock.py::MongoClientCollectionTest::test__insert
NOTE: If the MongoDB image was updated, or you want to try a different MongoDB version in
docker-compose
, you'll have to issue a docker compose down
before you do anything else to
ensure you're running against the intended version.
utcnow
When developing features that need to make use of "now," please use the libraries :code:`utcnow`
helper method in the following way:
.. code-block:: python
import mongomock
# Awesome code!
now_reference = mongomock.utcnow()
This provides users a consistent way to mock the notion of "now" in mongomock if they so choose.
Please see `utcnow docstring for more details <mongomock/helpers.py#L52>`_.
Branching model
The branching model used for this project follows the gitflow workflow
_. This means that pull
requests should be issued against the develop
branch and not the master
branch. If you want
to contribute to the legacy 2.x branch then your pull request should go into the support/2.x
branch.
Releasing
When ready for a release, tag the `develop` branch with a new tag (please keep semver names) and
push your tags to GitHub. The CI should do the rest.
To add release notes, create a release in GitHub's `Releases Page <https://github.com/mongomock/mongomock/releases>`_
then generate the release notes locally with:
.. code-block:: bash
python -c "from pbr import git; git.write_git_changelog()"
Then you can get the relevant section in the generated `Changelog` file.
Acknowledgements
----------------
Mongomock has originally been developed by `Rotem Yaari <https://github.com/vmalloc/>`_, then by
`Martin Domke <https://github.com/mdomke>`_. It is currently being developed and maintained by
`Pascal Corpet <https://github.com/pcorpet>`_ .
Also, many thanks go to the following people for helping out, contributing pull requests and fixing
bugs:
* Alec Perkins
* Alexandre Viau
* Austin W Ellis
* Andrey Ovchinnikov
* Arthur Hirata
* Baruch Oxman
* Corey Downing
* Craig Hobbs
* Daniel Murray
* David Fischer
* Diego Garcia
* Dmitriy Kostochko
* Drew Winstel
* Eddie Linder
* Edward D'Souza
* Emily Rosengren
* Eugene Chernyshov
* Grigoriy Osadchenko
* Israel Teixeira
* Jacob Perkins
* Jason Burchfield
* Jason Sommer
* Jeff Browning
* Jeff McGee
* Joël Franusic
* `Jonathan Hedén <https://github.com/jheden/>`_
* Julian Hille
* Krzysztof Płocharz
* Lyon Zhang
* `Lucas Rangel Cezimbra <https://github.com/Lrcezimbra/>`_
* Marc Prewitt
* Marcin Barczynski
* Marian Galik
* Michał Albrycht
* Mike Ho
* Nigel Choi
* Omer Gertel
* Omer Katz
* Papp Győző
* Paul Glass
* Scott Sexton
* Srinivas Reddy Thatiparthy
* Taras Boiko
* Todd Tomkinson
* `Xinyan Lu <https://github.com/lxy1992/>`_
* Zachary Carter
* catty (ca77y _at_ live.com)
* emosenkis
* hthieu1110
* יppetlinskiy
* pacud
* tipok
* waskew (waskew _at_ narrativescience.com)
* jmsantorum (jmsantorum [at] gmail [dot] com)
* lidongyong
* `Juan Gutierrez <https://github.com/juannyg/>`_
.. _examples in tests: https://github.com/mongomock/mongomock/blob/develop/tests/test__mongomock.py
.. _gitflow workflow: https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow
FAQs
Fake pymongo stub for testing simple MongoDB-dependent code
We found that mongomock demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 3 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
PyPI now allows maintainers to archive projects, improving security and helping users make informed decisions about their dependencies.
Research
Security News
Malicious npm package postcss-optimizer delivers BeaverTail malware, targeting developer systems; similarities to past campaigns suggest a North Korean connection.
Security News
CISA's KEV data is now on GitHub, offering easier access, API integration, commit history tracking, and automated updates for security teams and researchers.