Search code examples
javascriptsinonvault

Stub out node-vault import


How can the 'node-vault' module be stubbed out using Sinon.JS?

Here is the sample code to be tested:

const NodeVault = require('node-vault');

class BearerAuth {

  getVaultConfig (token) {
    return {
      apiVersion: 'v1',
      endpoint: app.get('vault'),
      token: token
    };
  }

  verify (token) {
    const vault = NodeVault(this.getVaultConfig(token));
    const resp = vault.tokenLookupSelf().then((result) => {
      console.log(`Vault token: ${token}, successfully authenticated.`);
      return Promise.resolve({
        'name': result.data.meta.username
      });
    }).catch((err) => {
      console.error(err.message);
      return Promise.reject(new this.ApplicationError.Authentication('Bearer token is incorrect.'));
    });
    return resp;
  }
}

module.exports = BearerAuth;
}

The test code which attempts to stub out the module using sinon.stub:

const assert = require('assert');
const sinon = require('sinon');
const nodeVault = require('node-vault');
const BearerAuth = require('bearer');


describe('Bearer AuthConfig', () => {
beforeEach(async () => {
    class TestBearerAuth extends BearerAuth {
      // override some other methods     
    }
    testAuth = new TestBearerAuth();
    const vaultConfig = {
        endpoint: 'http://localhost:8200',
        token: '123'
    };
    testAuth.getVaultConfig = sinon.stub.returns(vaultConfig);
  });

  it('returns user when valid token', async () => {
    const user = await testAuth.verify(null, 'mytoken');
    assert.deepEqual(user, {name: 'sre'});
  })
}

This fails when run with this error:

  1) Bearer Auth
       returns user when valid token:
     TypeError: Attempted to wrap undefined property undefined as function
      at wrapMethod (node_modules/sinon/lib/sinon/util/core/wrap-method.js:70:21)
      at TestBearerAuth.stub [as getVaultConfig] (node_modules/sinon/lib/sinon/stub.js:65:44)
      at TestBearerAuthConfig.verify (src/modules/auth/bearer.js:34:34)
      at Context.<anonymous> (test/unit/modules/auth/test-bearer.js:57:39)
      at processTicksAndRejections (internal/process/task_queues.js:97:5)

The node-vault library has the following export in index.d.ts:

declare function NodeVault(options?: NodeVault.VaultOptions): NodeVault.client;
export = NodeVault;

Solution

  • The unit test code from the node-vault library provided the solution:

    Test code:

    const assert = require('assert');
    const sinon = require('sinon');
    const nodeVault = require('node-vault');
    const BearerAuth = require('bearer');
    
    
    describe('Bearer AuthConfig', () => {
    beforeEach(async () => {
        request = sinon.stub();
        response = sinon.stub();
        response.statusCode = 200;
        response.body = {
          data: {
            meta: {
              username: 'jack'
            }
          }
        };
    
        request.returns({
          then (fn) {
            return fn(response);
          },
          catch (fn) {
            return fn();
          }
        });
        class TestBearerAuth extends BearerAuth {
           getVaultConfig (token) {
            return {
              endpoint: 'http://localhost:8200',
              token: '123',
              namespace: 'test',
              'request-promise': {
                defaults: () => request // dependency injection of stub
              }
            };
          }     
        }
        testAuth = new TestBearerAuth();
      });
    
      it('returns user when valid token', async () => {
        const user = await testAuth.verify(null, 'mytoken');
        assert.deepEqual(user, {name: 'sre'});
      })
    }
    
    

    Adding this here in case someone else runs into a similar issue.