0

I'm trying to unit test some express middleware which has dependencies on some classes I've made.

Middleware.js

const MyClass = require('../../lib/MyClass');

const myClassInstance = new MyClass();

    function someMiddleware(req, res) {
        myClassInstance.get().then(function(resp) {
          res.render('somefile.html');
        });
    };

Test.js

const MyClass = require('../../lib/MyClass');
const sinon = require('sinon');
const chai = require('chai');
const expect = chai.expect;

// File we are testing
const someMiddleware = require('path/to/middleware');

MyClassMock = sinon.spy(function() {
    return sinon.createStubInstance(MyClassMock);
});
describe('My Middleware', function() {

    let renderSpy, classStub;
    let res = {
        render: function() {}
    }

    beforeEach(function() {
        renderSpy = sinon.stub(res, 'render');
    })

    afterEach(function() {
        renderSpy.restore();
    })

    it('should call render function', function() {

        someMiddleware.someMiddleware(req, res);
        expect(renderSpy.calledOnce);

    });
});

I have tried a bunch of things however I can't quite seem to actually mock this class and mock the instance created! when it runs it will try to run the actual class with it's related dependencies inside.

Cheers folks!

Joey
  • 5
  • 4
  • There's a lot of confusion going on here :-) You have a lot of code that seems to be setup for you case, but isn't actually being used for _anything_ (example: `MyClassMock`, `MyClass`, ...). Maybe left-overs from editing? – oligofren Mar 28 '18 at 14:23

1 Answers1

0

Your Intent: replace/stub the dependencies of your middleware.

Your problem: this isn't possible from the outside of your module. You somehow need to "intercept" which code will be used.

There are two options, both of which I have written at length about in other places (1, 2, 3), so I'll do the shortform here:

Manual dependency injection

In your middleware module, provide a __setMyClassInstance(stubbedInstance) method that is only called from tests.

  • Pro: very easy, no frameworks needed
  • Con: test-only code that opens up your module

Link seams

This is about replacing require() calls in your code with another module loader that returns objects of your liking. In your test code:

const myMiddleware = proxyquire('../../src/middleware', { '../../lib/MyClass': myStubbedInstance })
  • Pro: Achieves the same as DI, but requires no code changes in the module
  • Con: not as clear cut what is going on, requires learning a new dependency

If you are stuck after looking at these very brief explanations, I suggest looking at my provided links for long-form explanations and links to tutorials on Link Seam libraries such as proxyquire and rewire.

oligofren
  • 20,744
  • 16
  • 93
  • 180
  • i dont like the idea of manual dependency like that changing module code but yeah thanks – Joey Apr 12 '18 at 12:42