如何在 Express Jest 测试中清理/重置 redis-mock?
How to clean-up / reset redis-mock in an Express Jest test?
我有一个应用程序可以统计 url 的访问次数。计数是在 Redis 中完成的。我正在使用 redis-mock
模拟内存中的 INCR
之类的命令。
以下测试访问页面 3 次并期望响应对象将 current
报告为 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();
});
});
问题是,如果我继续重复使用 app
,内部“redis”模拟将在测试之间继续增加。
我可以通过这样做稍微回避一下:
beforeEach(() => {
app = require('./app');
jest.resetAllMocks();
jest.resetModules();
});
覆盖应用程序似乎可以解决问题,但是没有办法在测试之间以某种方式清理“内部”模拟模块吗?
我的猜测是,套件中的其他一些测试以某种方式调用了“/test”端点,您可以尝试使用 .only
or even trying to run the entire suite serially.[=17 运行 套件的特定部分=]
要回答最初的问题,如果您正在 运行 一个特定的测试用例场景,或者如果您正在尝试 运行 整个套件,那么整个套件必须是独立和一致的,因此您需要清除任何可能实际影响结果的残留物。
所以其实可以用.beforeEach
or the .beforeAll
methods, provided by Jest in order to "mock" Redis and the .afterAll
的方法清关
虚拟实现如下所示:
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);
});
});
我有一个应用程序可以统计 url 的访问次数。计数是在 Redis 中完成的。我正在使用 redis-mock
模拟内存中的 INCR
之类的命令。
以下测试访问页面 3 次并期望响应对象将 current
报告为 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();
});
});
问题是,如果我继续重复使用 app
,内部“redis”模拟将在测试之间继续增加。
我可以通过这样做稍微回避一下:
beforeEach(() => {
app = require('./app');
jest.resetAllMocks();
jest.resetModules();
});
覆盖应用程序似乎可以解决问题,但是没有办法在测试之间以某种方式清理“内部”模拟模块吗?
我的猜测是,套件中的其他一些测试以某种方式调用了“/test”端点,您可以尝试使用 .only
or even trying to run the entire suite serially.[=17 运行 套件的特定部分=]
要回答最初的问题,如果您正在 运行 一个特定的测试用例场景,或者如果您正在尝试 运行 整个套件,那么整个套件必须是独立和一致的,因此您需要清除任何可能实际影响结果的残留物。
所以其实可以用.beforeEach
or the .beforeAll
methods, provided by Jest in order to "mock" Redis and the .afterAll
的方法清关
虚拟实现如下所示:
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);
});
});