node.jsmocha.jsproxyquire

mock require of oracledb using proxyquire to unit test node.js app


Please help to fix the below issue:

I am trying to unit test the dbAdapter module using mocha.

dbAdapter to connect to oracle and execute sql commands (dbAdapter.js)

const oracledb = require('oracledb');

let doConnect = function(callback) {
    oracledb.getConnection(config, callback); 
};


let execute_selectquery = function(query, results) {
    this.query = query;

    this.execute = function(connection, callback) {
        connection.execute(query, function(err, result) {
             if (err) {
                return callback(err);
            }else {
                callback(result);
            }

        })
};

unit test to test the select query: (test.js)

describe(`test proxyquire`, function() {
            const proxyquire =  require('proxyquire')
            let dbAdapter
            let oracledbStub;

            before(function() {

                oracledbStub = {
                    model: function() {
                        return {
                            updateDb: function(id, first, last, callback) {
                                callback(null, 'done'); 
                            } 
                        };
                    } 
                };

            dbAdapter = proxyquire('../controllers/dbAdapter.js', {'oracledb': oracledbStub});
            });  

            it.only(`test route`, function(done) {
                let query = "select * from users";
                db.execute_selectquery(query, function(err, result){
                    console.log(result)
                })

            }) 
})  

In the above unit test I have used proxyquire so that I can use my mocked oracledbStub instead of oracledb in dbAdapter.js

When I run the unit test I get the below error:

Uncaught TypeError: Illegal invocation
      at Function.getConnection (node_modules/oracledb/lib/oracledb.js:295:10)
      at Function.getConnection (node_modules/oracledb/lib/util.js:99:19)
      at doConnect (controllers/dbConnection/oracleAdapter.js:47:14)
      at fn (node_modules/async/lib/async.js:641:34)
      at Immediate.<anonymous> (node_modules/async/lib/async.js:557:34)

I followed the below blog: http://www.devblogrbmz.com/nodejs-mocking-with-proxyquire/

I believe I might be missing some detail and have been stuck since a day.


Solution

  • If you look at the example that you based your code on, you'll notice that mongooseStub is an object with a model method that is meant to override the model method that's included with Mongoose. If that method doesn't exist on the stub, then the method from Mongoose would have been used instead.

    In your case, you've defined the oracleStub with an object that has a model function. However, oracledb doesn't have a model method - so that's not going to do anything. Your stub should include a getConnection function since that's what you're trying to override from the base class (oracledb).

    This will get tricky as you then have to have a stub for a connection object and its methods, like execute. The more methods you use in the actual library, the more work you'll have stubbing it all out.

    There's a similar question here: How to stub oracledb with sinon?