title: How to connect to mongoDB and test for drop collection?
body: <p>This is how I connect to a mongoDB using <code>monk()</code>. I'll store it in <code>state</code>.</p>
  
  <p>Assume we want to drop some collections, we call <code>dropDB</code>.</p>
  
  <p><strong>db.js</strong></p>
  
  <pre><code>var state = {
    db: null
  }
  
  export function connection () {
    if (state.db) return
    state.db = monk('mongdb://localhost:27017/db')
    return state.db
  }
  
  export async function dropDB () {
    var db = state.db
    if (!db) throw Error('Missing database connection')
  
    const Users = db.get('users')
    const Content = db.get('content')
  
    await Users.remove({})
    await Content.remove({})
  }
  </code></pre>
  
  <p>I'm not quite sure if it is a good approach to use <code>state</code> variable. Maybe someone can comment on that or show an improvement.</p>
  
  <p>Now I want to write a unit test for this function using JestJS:</p>
  
  <p><strong>db.test.js</strong></p>
  
  <pre><code>import monk from 'monk'
  import { connection, dropDB } from './db'
  jest.mock('monk')
  
  describe('dropDB()', () =&gt; {
    test('should throw error if db connection is missing', async () =&gt; {
      expect.assertions(1)
      await expect(dropDB()).rejects.toEqual(Error('Missing database connection'))
    })
  })
  </code></pre>
  
  <p>This part is easy, but the next part gives me two problems:</p>
  
  <p>How do I mock the <code>remove()</code> methods?</p>
  
  <pre><code>  test('should call remove() methods', async () =&gt; {
      connection() // should set `state.db`, but doesn't work
      const remove = jest.fn(() =&gt; Promise.resolve({ n: 1, nRemoved: 1, ok: 1 }))
      // How do I use this mocked remove()?
      expect(remove).toHaveBeenCalledTimes(2)
    })
  </code></pre>
  
  <p>And before that? How do I setup <code>state.db</code>?</p>
  
  <hr>
  
  <p><strong>Update</strong></p>
  
  <p>As explained by <em>poke</em> the global variable makes the problem. So I switched to a class:</p>
  
  <p><strong>db.js</strong></p>
  
  <pre><code>export class Db {
    constructor() {
      this.connection = monk('mongdb://localhost:27017/db');
    }
  
    async dropDB() {
      const Users = this.connection.get('users');
      const Content = this.connection.get('content');
  
      await Users.remove({});
      await Content.remove({});
    }
  }
  </code></pre>
  
  <p>which results in this test file:</p>
  
  <p><strong>db.test.js</strong></p>
  
  <pre><code>import { Db } from './db'
  jest.mock('./db')
  
  let db
  let remove
  
  describe('DB class', () =&gt; {
    beforeAll(() =&gt; {
      const remove = jest.fn(() =&gt; Promise.resolve({ n: 1, nRemoved: 1, ok: 1 }))
      Db.mockImplementation(() =&gt; {
        return { dropDB: () =&gt; {
          // Define this.connection.get() and use remove as a result of it
        } }
      })
    })
    describe('dropDB()', () =&gt; {
      test('should call remove method', () =&gt; {
        db = new Db()
        db.dropDB()
        expect(remove).toHaveBeenCalledTimes(2)
      })
    })
  })
  </code></pre>
  
  <p>How do I mock out any <code>this</code> elements? In this case I need to mock <code>this.connection.get()</code></p>