代码之家  ›  专栏  ›  技术社区  ›  dsp_099

如何在ExpressJest测试中清除/重置redis-mock?

  •  0
  • dsp_099  · 技术社区  · 4 年前

    我有一个应用程序,它统计访问网址的次数。理货是在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”mock将在测试之间继续递增。

    我可以通过这样做来回避这一点:

    beforeEach(() => {
      app = require('./app');
      jest.resetAllMocks();
      jest.resetModules();
    });
    

    重写应用程序似乎起到了作用,但在测试之间,难道没有办法清理“内部”模拟模块吗?

    0 回复  |  直到 4 年前
        1
  •  2
  •   vorillaz    4 年前

    我的猜测是,“/test”端点在套件中的其他一些测试中被调用,您可以尝试使用 .only 甚至试图运行整个套件 serially .

    为了回答最初的问题,如果您正在运行特定的测试用例场景,或者您正在尝试运行整个套件,那么整个套件必须是孤立和一致的,因此您需要清除任何可能实际影响结果的遗留问题。

    所以你可以实际使用 .beforeEach 或者 .beforeAll 方法,由Jest提供,以便“模拟”Redis和 .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);
      });
    });