Reputation: 6121
I have an app which tallies the number of visits to the url. The tallying is done in Redis. I'm using redis-mock
which simulates commands like INCR
in memory.
The following test visits the page 3 times and expects the response object to report current
as 3
:
let app = require('./app');
const supertest = require("supertest");
jest.mock('redis', () => jest.requireActual('redis-mock'));
/* Preceeded by the exact same test */
it('should report incremented value on multiple requests', (done) => {
const COUNT = 3;
const testRequest = function (cb) { supertest(app).get('/test').expect(200, cb) };
async.series([
testRequest,
testRequest,
testRequest
], (err, results) => {
if (err) console.error(err);
const lastResponse = _.last(results).body;
expect(
lastResponse.current
).toBe(COUNT);
done();
});
});
The issue is that if I keep reusing app
, the internal "redis" mock will continue getting incremented between tests.
I can side-step this a bit by doing this:
beforeEach(() => {
app = require('./app');
jest.resetAllMocks();
jest.resetModules();
});
Overwriting app seems to do the trick but isn't there a way to clean-up the "internal" mocked module somehow between tests?
Upvotes: 4
Views: 2930
Reputation: 6266
My guess is that somehow the '/test' endpoint gets invoked in some other tests in the suite, you could try to run specific parts of your suite using .only
or even trying to run the entire suite serially.
To answer the original questions the entire suite must be isolated and consistent either if you are running a specific test case scenario or if you are trying to run the entire suite, thus you need to clear up any leftovers that they could actually affect the results.
So you can actually use the .beforeEach
or the .beforeAll
methods, provided by Jest in order to "mock" Redis and the .afterAll
method for clearance.
A dummy implementation would look like this:
import redis from "redis";
import redis_mock from "redis-mock";
import request from "supertest";
jest.mock("redis", () => jest.requireActual("redis-mock"));
// Client to be used for manually resetting the mocked redis database
const redisClient = redis.createClient();
// Sometimes order matters, since we want to setup the mock
// and boot the app afterwards
import app from "./app";
const COUNT = 3;
const testRequest = () => supertest(app).get("/test");
describe("testing", () => {
afterAll((done) => {
// Reset the mock after the tests are done
jest.clearAllMocks();
// You can also flush the mocked database here if neeeded and close the client
redisClient.flushall(done);
// Alternatively, you can also delete the key as
redisClient.del("test", done);
redisClient.quit(done);
});
it("dummy test to run", () => {
expect(true).toBe(true);
});
it("the actual test", async () => {
let last;
// Run the requests in serial
for (let i = 0; i < COUNT - 1; i++) {
last = await testRequest();
}
// assert the last one
expect(last.status).toBe(200);
expect(last.body.current).toBe(COUNT);
});
});
Upvotes: 2