title: Using a fake mongoDB for pytest testing
body: <p>I have code that connects to a MongoDB Client and I'm trying to test it. For testing, I don't want to connect to the actual client, so I'm trying to figure out make a fake one for testing purposes. The basic flow of the code is I have a function somewhere the creates a <code>pymongo</code> client, then queries that and makes a dict that is used elsewhere.</p>
  
  <p>I want to write some tests using pytest that will test different functions and classes that will call <code>get_stuff</code>. My problem is that <code>get_stuff</code> calls <code>mongo()</code> which is what actually makes the connection to the database. I was trying to just use <code>pytest.fixture(autouse=True)</code> and <code>mongomock.MongoClient()</code> to replace <code>mongo()</code>.</p>
  
  <p>But this isn't replacing the <code>mongo_stuff.mongo()</code>. Is there some way I can tell pytest to replace a function so my <code>fixture</code> is called instead of the actual function? I thought making the <code>fixture</code> would put my testing <code>mongo()</code> higher priority in the namespace than the function in the actual module.</p>
  
  <p>Here is an example file structure with my example:</p>
  
  <pre><code>.
  ├── project
  │   ├── __init__.py
  │   ├── mongo_stuff
  │   │   ├── __init__.py
  │   │   └── mongo_stuff.py
  │   └── working_class
  │       ├── __init__.py
  │       └── somewhere_else.py
  └── testing
      ├── __init__.py
      └── test_stuff.py
  </code></pre>
  
  <p><strong>mongo_stuff.py</strong></p>
  
  <pre><code>import pymongo
  
  def mongo():
      return pymongo.MongoClient(connection_params)
  
  def get_stuff():
      db = mongo()  # Makes the connection using another function
      stuff = query_function(db)  # Does the query and makes a dict
      return result
  </code></pre>
  
  <p><strong>somewhere_else.py</strong></p>
  
  <pre><code>from project.mongo_stuff import mongo_stuff
  
  mongo_dict = mongo_stuff.get_stuff()
  </code></pre>
  
  <p><strong>test_stuff.py</strong></p>
  
  <pre><code>import pytest
  import mongomock
  
  @pytest.fixture(autouse=True)
  def patch_mongo(monkeypatch):
      db = mongomock.MongoClient()
      def fake_mongo():
          return db
      monkeypatch.setattr('project.mongo_stuff.mongo', fake_mongo)
  
  from poject.working_class import working_class  # This starts by calling project.mongo_stuff.mongo_stuff.get_stuff()
  </code></pre>
  
  <p>And this will currently give me a connection error since the <code>connection params</code> in <strong>mongo_stuff.py</strong> are only made to work in the production environment. If I put the <code>import</code> statement from <strong>test_stuff.py</strong> into a test function, then it works fine and <code>mongomock</code> db will be used in the testing enviornment. I also tried change the <code>setattr</code> to <code>monkeypatch.setattr('project.working_class.mongo_stuff.mongo', fake_mongo)</code> which also does not work.</p>