jbrumwell / mock-knex

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

"conn.transaction is not a function" with MSSQL #95

Open hijaq opened 4 years ago

hijaq commented 4 years ago

Hey, first of all, thanks for that useful package! Now the issue... I'm trying to use mock-knex with MSSQL (no connection to db) and it fails when I try to call transaction method, here's a sample code to reproduce:

const knex = require('knex');
const mockKnex = require('mock-knex');

const mockDb = knex({ client: 'mssql' });
const tracker = mockKnex.getTracker();

const getSome = async (db) => {
  await db.transaction().then((trx) => {
    console.log('started transaction');
    return trx;
  });
  return 1;
};

describe('test', () => {
  beforeAll(() => {
    mockKnex.mock(mockDb);
  });
  afterAll(() => {
    mockKnex.unmock(mockDb);
  });
  beforeEach(() => {
    tracker.install();
  });
  afterEach(() => {
    tracker.uninstall();
  });
  test('should call', async () => {
    tracker.on('query', (query) => {
      query.response([]);
    });
    const result = await getSome(mockDb);
    expect(result).toEqual(1);
  });
});

and the error is:

test
    ✕ should call (8ms)

  ● test › should call

    TypeError: conn.transaction is not a function

      at node_modules/knex/lib/dialects/mssql/transaction.js:81:27
      at tryCatcher (node_modules/bluebird/js/release/util.js:16:23)
      at Promise._settlePromiseFromHandler (node_modules/bluebird/js/release/promise.js:517:31)
      at Promise._settlePromise (node_modules/bluebird/js/release/promise.js:574:18)
      at Promise._settlePromiseCtx (node_modules/bluebird/js/release/promise.js:611:10)
      at _drainQueueStep (node_modules/bluebird/js/release/async.js:142:12)
      at _drainQueue (node_modules/bluebird/js/release/async.js:131:9)
      at Async.Object.<anonymous>.Async._drainQueues (node_modules/bluebird/js/release/async.js:147:5)
      at Immediate.Async.drainQueues [as _onImmediate] (node_modules/bluebird/js/release/async.js:17:14)

used version:

treffynnon commented 4 years ago

I have the same issue. My current workaround is to create my own implementation of the mock spec:

import Promise from 'bluebird'
import _ from 'lodash'

// tslint:disable: no-submodule-imports
// @ts-ignore
import { spec } from 'mock-knex/dist/platforms/knex/0.11'
// @ts-ignore
import { makeClient } from 'mock-knex/dist/platforms/knex/0.8'
// tslint:enable: no-submodule-imports

// tslint:disable-next-line: no-namespace
namespace MSSQLMockKnex {
    class MockTransaction {
        public async begin() {
            return this
        }
        // tslint:disable: no-empty
        public async commit() {}
        public async request() {}
        public async rollback() {}
        // tslint:enable: no-empty
    }
    interface Connection {
        __knexUid: string
        timeout: any
        transaction: () => MockTransaction
    }
    const connection: Connection = {
        __knexUid: 'mockedConnection',
        timeout: Promise.method(getConnection),
        transaction: () => new MockTransaction(),
    }
    function getConnection() {
        return { ...connection }
    }
    export const newSpec = _.defaultsDeep(
        {
            replace: [
                {
                    client: {
                        acquireConnection() {
                            return Promise.resolve(getConnection())
                        },
                        // tslint:disable-next-line: no-empty
                        destroyRawConnection() {},
                    },
                },
            ],
        },
        spec
    )

    export const client = makeClient(newSpec)
}

Then to use it:

const db = knex({ client: 'mssql' })
MSSQLMockKnex.client.mock(db)
// now you can use db to create mock MSSQL transactions
PhakornKiong commented 3 years ago

@treffynnon

I've tried the code you've given with hijaq's code, but I'm still getting this error.

    TypeError: conn.beginTransaction is not a function
      at node_modules/knex/lib/dialects/mssql/transaction.js:8:12
      at Transaction_MSSQL.begin (node_modules/knex/lib/dialects/mssql/transaction.js:7:12)
      at node_modules/knex/lib/execution/transaction.js:203:16
      at Transaction_MSSQL.acquireConnection (node_modules/knex/lib/execution/transaction.js:254:20)

I did try to do this, but the test just goes on never ending land.

const connection = {
  __knexUid: 'mockedConnection111',
  timeout: Promise.method(getConnection),
  transaction: () => new MockTransaction()
  beginTransaction: () => new MockTransaction()
};