14

I have been struggling a lot to mock database in one of my side projects while writing junits. Can somebody please help me out here. Below is what the scenario looks like:

Before that, the source code is here - https://github.com/sunilkumarc/track-courier

  1. I have created a model using sequelize module in Nodejs. And I access my db through this model.

  2. I want to mock the db calls when running junits. For example findOne method here which returns a promise (https://github.com/sunilkumarc/track-courier/blob/master/models/parcels.js#L4). Basically when running this particular endpoint I want to skip accessing the db.

Any help is appreciated!

Regards, Sunil

Sunil Kumar
  • 535
  • 6
  • 13
  • 3
    Possible duplicate of [Mocking database in node.js?](http://stackoverflow.com/questions/12526160/mocking-database-in-node-js) – Hodrobond Feb 22 '17 at 17:51
  • 1
    Take a look on [proxyquire](https://www.npmjs.com/package/proxyquire) – Jaime Feb 22 '17 at 21:09
  • 1
    Also, your [current tests](https://github.com/sunilkumarc/track-courier/blob/master/test/parcels.js) looks to me more like integration/e2e tests than unit test. Check this [Writing great unit test](http://blog.stevensanderson.com/2009/08/24/writing-great-unit-tests-best-and-worst-practises/) – Jaime Feb 22 '17 at 21:15
  • @Hodrobond Yes. Looks like it is duplicate. I don't know how I missed it. Thanks for pointing out. – Sunil Kumar Feb 23 '17 at 05:56
  • @Jaime Thanks for the link. I will go through it. – Sunil Kumar Feb 23 '17 at 05:56

2 Answers2

1

While people have pointed out in the comments to a similar question that it's probably wise to include a test Database, I'm going to answer the question directly.

Utilizing Jest, you can do the following to mock individual calls on specific models

const myUser = User.build({
  ...attributes,
});

jest.spyOn(User, 'findOne').mockImplementation((options) => Promise.resolve(myUser));

const mockedUser = await User.findOne({});

In my experience, I do agree with the commenters. Mocking specific functions like these are not always the most useful as they may not accurately depict the return values of a specific Sequelize function. For example, User#findOne may return null. If you provide rejectOnEmpty, you will have to build your own logic for handling this, which may differ from the exact logic used in the Sequelize library.

Ultimately your code is likely responsible for handling whatever Sequelize returns correctly, and with the level of integration to your data layer, this is going to be something very difficult to mock correctly - not to mention extremely tedious.

Documentation to Model#findAll, where you can see rejectOnEmtpy: https://sequelize.org/api/v6/class/src/model.js~model#static-method-findAll

Andrew T
  • 81
  • 5
0

I used to use Sinon.JS for mocking anything, in this case I did it as:

// assume "Users" is our table

sinon.replace(Users, "create", () => console.log(`mocked "Users" table's "create" method`));
David Gabrielyan
  • 227
  • 2
  • 12