Mocking third party library (ioredis) in typescript tests

3k Views Asked by At

I am having a surprisingly hard time being able to mock a third party library in my typescript tests.

I am making a library based upon this typescript-starter library. It uses ava for testing.

In my case I am trying to mock the main class of ioredis so that my tests does not try to set up real database connections.

I have tried to use sinon, testdouble.js, and mockery.

In sinon I have tried the following

let redisStub = sinon.stub(IORedis)
sinon.assert.called(redisStub.Cluster)

With testdouble I have tried a whole bunch of things, including;

td.replace('ioredis') // #1
td.replace('./homeMadeIoredisWrapperClass') // #2

I have tried mockery

mockery.enable()
mockery.registerMock('ioredis', {some: 'object'})

I have also tried numerous other variation, like always using require('ioredis') in the methods

Am I trying to do something impossible here? I though stubbing/mocking a database was a very normal thing to do, but I can't seem to figure it out.

Maybe my design is flawed and I am perhaps trying to mock the wrong things? Some help would be much appreciated!


Ps. In the case it matters, I am trying to create a pretty simple ioredis connection wrapper.

2

There are 2 best solutions below

0
On BEST ANSWER

I had a couple of misunderstandings / issues with my code which caused this. Perhaps this can enlighten someone else stumbling upon this;

  1. I was requiring "everything" (import { MyLibrary } from "myLibrary") before the td.replace which made the replace statement happen after the code had required the module. The reason was that the example test were designed a specific way in typescript-starter repo. I have now made a PR to fix the underlying problem.
  2. I was running the ava tests in parallel, which caused the td.reset() to happen before some of my callbacks had fired, effectively preventing the replace to work in many cases. The solution in ava, use test.serial(... in stead of test(.... Yes, the test will run slower, but they will work. You can make a separate file for each test to get true parallel runs in ava.

There are also some useful wiki entries in the testdouble GitHub page; https://github.com/testdouble/contributing-tests/wiki/Don%27t-mock-what-you-don%27t-own https://github.com/testdouble/contributing-tests/wiki/SAFE-test

Hope someone finds this useful.

0
On

You can mock ioredis (version 4.16.2) with just sinon. You have to mock the connect method.

import ioredis from "ioredis";

sinon.stub(ioredis.prototype, "connect").returns(Promise.resolve());
sinon.stub(ioredis.prototype, "get").returns(Promise.resolve({ data: "hello" }));