jbrumwell / mock-knex

A mock knex adapter for simulating a database during testing
MIT License
239 stars 71 forks source link

unmock does not work correctly #126

Open sl-ffx opened 3 years ago

sl-ffx commented 3 years ago

The unmock method does not work as expected. I would expect to have the original client working as it would never have been mocked. After unmock the client always throw an error on executing a query:

TypeError: Cannot read property 'response' of undefined
    at Client_PG.processResponse (project/node_modules/knex/lib/dialects/postgres/index.js:247:22)
    at project/node_modules/knex/lib/runner.js:162:28
    at tryCatcher (project/node_modules/bluebird/js/release/util.js:16:23)
    at Promise._settlePromiseFromHandler (project/node_modules/bluebird/js/release/promise.js:547:31)
    at Promise._settlePromise (project/node_modules/bluebird/js/release/promise.js:604:18)
    at Promise._settlePromise0 (project/node_modules/bluebird/js/release/promise.js:649:10)
    at Promise._settlePromises (project/node_modules/bluebird/js/release/promise.js:729:18)
    at _drainQueueStep (project/node_modules/bluebird/js/release/async.js:93:12)
    at _drainQueue (project/node_modules/bluebird/js/release/async.js:86:9)
    at Async._drainQueues (project/node_modules/bluebird/js/release/async.js:102:5)
    at Immediate.Async.drainQueues [as _onImmediate] (project/node_modules/bluebird/js/release/async.js:15:14)
    at processImmediate (internal/timers.js:461:21)

I'm using mock-knex v0.4.9 knex v0.21.19

Here is a code example to get the error

const knex = require('knex')
const mockDb = require('mock-knex')

const db = knex({
  client: 'pg'
})

mockDb.mock(db)
mockDb.unmock(db)

db.raw('SELECT 10;')
  .then(console.log)
  .catch(console.error)

If you remove the mock and unmock lines the query works.

sl-ffx commented 3 years ago

At the moment I'm using following quickfix

const mockBackup = {}
mockBackup._stream = db.client.constructor.prototype._stream
mockBackup._query = db.client.constructor.prototype._query
mockBackup.processResponse = db.client.constructor.prototype.processResponse

mockDb.mock(db)
mockDb.unmock(db)

db.client.constructor.prototype._stream = mockBackup._stream
db.client.constructor.prototype._query = mockBackup._query
db.client.constructor.prototype.processResponse = mockBackup.processResponse
LogansUA commented 1 year ago

Hey, I'm having a similar issue with knex >= v0.95, but thanks to the @sl-ffx I was able to fix it. Is there anyone who can actually fix it in mock-knex?

danthegoodman commented 1 year ago

I opened an MR to fix this. If you want to monkey-patch it yourself, you can use this code (tested only with v0.4.11)

const transformer = Object.getPrototypeOf(require("mock-knex/dist/util/transformer"));
const _lodash2 = {default:require("lodash")}; // needed by the new function
const newFn = transformer._replace.toString()
  .replace(".replace('._constructor.', '.constructor.')", ".replace('._constructor.', '.constructor.').replace('._prototype.', '.prototype.')")
  .replace(".replace('.constructor.', '._constructor.')", ".replace('.constructor.', '._constructor.').replace('.prototype.', '._prototype.')");
transformer._replace = eval("(" + newFn + ")");
barwin commented 1 year ago

We only started experiencing this error when we introduced semantic-release (versions 9 and later) as a dependency in our project. The fix in #138 solved the issue for us. Thanks @danthegoodman !