0

I have 2 files controller.js and entity.js which interact with each other. I am testing controller.js, and it creates an instance of entity.js (class) and use one of its functions. How can I stub/mock/spy the call and the return of that method?

controller.js

const controller= async (req, res) => {

try {
    ...

    const entity = new Entity({
    ...
    });

    const validation = await entity.validate();

    ...
    return res.send()
    }
  } catch (error) {
    return res.send(error)
  }
};

Entity.js

class Entity{
  constructor() {
  ...
  }

  ...

  async validate() {
    ...
    return response;
  }
}

Any idea how to test controller.js using supertest, sinon and chai?

Menticolcito
  • 769
  • 1
  • 5
  • 11
  • 1
    I'd suggest looking into dependency inversion - this would be much easier to test if the controller didn't new up something it depended on. – jonrsharpe Nov 16 '18 at 16:26

2 Answers2

1

Sinon will happily stub the function. Since it's a class method you just need to be sure to stub the function on the prototype:

const controller = async (req, res) => {
      const entity = new Entity();
      const validation = await entity.validate();
      console.log(validation)
  };
  
class Entity{
    constructor() {}
    async validate() {
      return "real function";
    }
}
// stub it
let stub = sinon.stub(Entity.prototype, 'validate')
stub.returns('stubbed function')

controller()
<script src="https://cdnjs.cloudflare.com/ajax/libs/sinon.js/7.1.1/sinon.min.js"></script>
Mark
  • 90,562
  • 7
  • 108
  • 148
0

This solution uses Ava (but you should be able to adapt to Mocha easily). However I'm more familiar with testdouble. If you have no success with sinon (I'm sure you will), here's an alternative that you may want to consider.

So if we have burrito.js:

module.exports = class {
   eat() {
      return '';
   }
};

And lunch.js:

var Burrito = require('./burrito');
module.exports = () => (new Burrito()).eat();

Then in your test:

const td = require('testdouble');
const test = require('ava');

test('swap burrito', t => {

  td.replace('./burrito', class FakeBurrito  {
    eat() {
      return '';
    }
  });

  const lunch = require('./lunch');

  t.is(lunch(), ''); // PASS
  t.is(lunch(), ''); // FAIL
});

The key is to require your dependency (a burrito) before your subject under test (your lunch) requires it, so that you have time to fake it.

customcommander
  • 17,580
  • 5
  • 58
  • 84