pytest-mongo icon indicating copy to clipboard operation
pytest-mongo copied to clipboard

Option to start DB as single-member replica set

Open languitar opened this issue 3 years ago • 0 comments

Some MongoDB features such as change streams do not work with standalone instances. In that case a replica set is required. It would be nice if there was an option to start a database as a single-member replica set for being able to use change streams, transactions etc. also in tests.

Here is workaround that I am currently using in most affected projects. As this is required more often, it would be nice if this was part of the pytest-plugin itself:

@pytest.fixture(scope="session")
def mongo_repl_proc(mongo_proc):
    client = pymongo.MongoClient(f"mongodb://{mongo_proc.host}:{mongo_proc.port}")
    client.admin.command("replSetInitiate")
    time.sleep(1)
    return mongo_proc


@pytest.fixture
def mongo(mongo_repl_proc):  # noqa: CCR001
    """
    Provide an empty mongodb client.

    This is a modification of the fixture from pytest-mongo to support replica
    sets. These require returning a client that specifically knows about them.
    """
    client = pymongo.MongoClient(
        f"mongodb://{mongo_repl_proc.host}:{mongo_repl_proc.port}",
        replicaset="rep0",
        tz_aware=True,
        # Ensures that write operations in tests are always visible to subsequent reads
        # without using explicit sessions.
        journal=True,
    )

    # wait for nodes
    while not client.nodes:
        time.sleep(0.1)

    yield client

    # clean the database
    for db_name in client.list_database_names():
        if db_name == "config":
            continue
        database = client[db_name]
        for collection_name in database.list_collection_names():
            collection = database[collection_name]
            # Do not delete any of Mongo system collections
            if (
                collection.name.startswith("system.")
                or collection.name.startswith("oplog.")
                or collection.name.startswith("replset.")
            ):
                continue
            collection.drop()

An in pytest.ini:

mongo_params = --replSet rep0

languitar avatar Mar 25 '21 16:03 languitar