title: Test of node.js method using knex with sqlite3 never stops
body: <h2>What I want to do</h2>
  
  <p>I'm trying to test a <code>node.js</code> function which uses <code>knex</code>.</p>
  
  <p>Instead of just mocking <code>knex</code>, I think it's interesting to actually run the test on an in-memory database, which makes this test not strictly unitary, but it's, to me, the only useful way to test a <code>repository</code> class.</p>
  
  <p>It's also the most voted answer here: <a href="https://stackoverflow.com/a/32749601/1187067">https://stackoverflow.com/a/32749601/1187067</a></p>
  
  <h2>What I use in my test</h2>
  
  <ul>
  <li>A simplified book repository <code>bookRepo.js</code> based on <code>knex</code></li>
  <li>A test <code>bookRepo.test.js</code> injecting a <code>knex</code> connection based on <code>SQLite3</code>.</li>
  </ul>
  
  <h2>Problem</h2>
  
  <p>The database is well initialize, the test succeeds and the <code>afterEach()</code> function is well invoked, but the process <strong>never ends</strong> which is particularly problematic for pipelines.</p>
  
  <p>The only way I found to stop the process is to call <code>knex.destroy()</code> in both bookRepo.js and bookRepo.test.js, but it is not possible to destroy knex because it won’t be possible to use it more than once.</p>
  
  <p>Thanks for helping!</p>
  
  <h2>Code</h2>
  
  <p><strong>bookRepo.js</strong></p>
  
  <pre class="lang-js prettyprint-override"><code>const knex = require('connection'); // dependency not injected in constructor
  
  const TABLE = 'books';
  
  class BookRepo {
    constructor() {
      this.knex = knex;
    }
  
    static getTable() {
      return TABLE;
    }
  
    async getTitleById(id) {
      const book = await this.knex(TABLE)
        .select('title')
        .where('id', id)
        .first();
  
      return book.title;
    }
  }
  
  module.exports = BookRepo;
  </code></pre>
  
  <p><strong>bookRepo.test.js</strong></p>
  
  <pre class="lang-js prettyprint-override"><code>const { assert } = require('chai');
  const mock = require('mock-require');
  const {
    describe,
    it,
    before,
    after,
    beforeEach,
    afterEach,
  } = require('mocha');
  
  const sqliteConf = {
    client: 'sqlite3',
    connection: {
      filename: ':memory:',
    },
    useNullAsDefault: true,
  };
  const knex = require('knex')(sqliteConf);
  
  const booksTable = BookRepo.getTable();
  const BOOK_1 = {
    id: 1,
    title: 'Batman',
  };
  
  let bookRepo;
  
  describe('getTitleById', () =&gt; {
    before(() =&gt; {
      // To use sqlite3 in the tested module, replace knexfile (required by connections)
      mock('../knexfile', {
        development: sqliteConf,
      });
  
      // as knex is not injected in constructor, we need to require BookRepo after having mocked knexfile.
      const BookRepo = require('../bookRepo');
      bookRepo = new BookRepo();
    });
  
    after(() =&gt; {
      mock.stopAll();
      knex.destroy(); // destroys only the connection of the test, not in bookRepo
    });
  
    /**
     * We initialize the SQLite database before each test (create table and insert)
     */
    beforeEach(async () =&gt; {
      // drop table
      await knex.schema.dropTableIfExists(booksTable);
  
      // create table
      await knex.schema.createTable(booksTable, (table) =&gt; {
        table.integer('id');
        table.string('title');
      });
  
      // Insertion
      await knex.transaction((t) =&gt; knex(booksTable)
        .transacting(t)
        .insert(BOOK_1)
        .then(t.commit)
        .catch(t.rollback))
        .catch((e) =&gt; {
          console.error(e);
          throw new Error('failed to insert test data');
        });
    });
  
    /**
     * We drop the SQLite table after each test
     */
    afterEach(async () =&gt; {
      await knex.schema.dropTableIfExists(booksTable); // table well dropped
    });
  
    it('returns the title of the given book', async () =&gt; {
      const bookRepo = new BookRepo();
  
      const expectedTitle = BOOK_1.title;
      const retrievedTitle = await bookRepo.getTitleById(BOOK_1.id);
  
      assert.equal(retrievedTitle, expectedTitle); // OK
    });
  });
  </code></pre>
  
  <p><strong>package.json</strong></p>
  
  <pre><code>…
  dependencies": {
      "knex": "^0.20.1",
   },
    "devDependencies": {
      "chai": "latest",
      "mocha": "^6.2.2",
      "sqlite3": "latest",
    }
  }
  </code></pre>