user108471
user108471

Reputation: 2607

How can I mock a dependency's class in a module I test with pytest?

I have a test module, test_roles.py which is trying to test the module roles.py. I want to mock out the use of MongoClient from pymongo within the roles module, so that my unit tests do not rely on an external service. The following is a simplified example of what I'm doing that isn't working for me. How do I get this to work so that I can fake out MongoClient everywhere?

In roles.py:

from pymongo import MongoClient
client = MongoClient(...)

In test_roles.py:

import roles
def test_mock():
    assert type(roles.client).__name__ == 'FakeMongoClient'

In conftest.py:

import pytest
import pymongo

@pytest.fixture(autouse=True)
def fake_mongo(monkeypatch):
    class FakeMongoClient():
         pass
    monkeypatch.setattr(pymongo, 'MongoClient', FakeMongoClient)

I don't believe the question identified as a duplicate is asking the same thing. Editing a module's global variable after-the-fact is different from modifying the dependency such that the actions that occur during import use the mocked dependency. In this example, unless the MongoClient initialization uses lazy connections, failing to mock before first import means we get a failure during import of roles.

Upvotes: 0

Views: 1041

Answers (1)

chepner
chepner

Reputation: 532003

roles.py uses roles.MongoClient, not pymongo.MongoClient, to define roles.client, due to how you imported the name. You need to patch the same:

monkeypatch.setattr(roles, 'MongoClient', FakeMongoClient)

Your original patch should work if roles.py looked like

import pymongo
client = pymongo.MongoClient()

Upvotes: 3

Related Questions