【问题标题】:Jest mock third-party default export per individual test每个单独测试的 Jest 模拟第三方默认导出
【发布时间】:2021-12-28 00:21:28
【问题描述】:

我正在尝试使用jestsupertest 测试express 控制器。我有一个使用multer 处理文件的中间件。我可以在全球范围内模拟 multer,但我无法根据 it/test 案例模拟它。

// saveImage.controller.ts
jest.mock('multer', () => {
  const m = () => ({
    single: () => (req: Request, res: Response, next: NextFunction) => {
      req.body = { type: 'screenshots' };
      req.file = mockFile;
      return next();
    },
  });
  m.memoryStorage = () => jest.fn();
  return m;
});

describe('POST /api/v1/garment/image/upload', () => {
  it('should return 201', async () => {
    await request(app)
      .post('/api/v1/garment/image/upload')
      .send({ file: 'myImage' }) // this is overwritten by the mock 
      .expect(201); // passes
  });

  it('should return 400', async () => {
    await request(app)
      .post('/api/v1/garment/image/upload')
      .send() // this is overwritten by the mock
      .expect(400); // fails
  });
});

第一个测试通过,但我无法更改模拟以使第二个测试通过。 如何在我的第二个it 案例中更改模拟?

【问题讨论】:

    标签: node.js express unit-testing jestjs supertest


    【解决方案1】:

    我将使用jest.doMock(moduleName, factory, options) 模拟multer。注意multer.single()方法会在模块被导入的时候执行,所以我们在模块被导入之前就mock了。

    为了在导入模块时清除缓存(可以缓存模块作用域变量、函数的函数等),需要在运行每个测试用例之前使用jest.resetModules()

    app.ts:

    import express from 'express';
    import multer from 'multer';
    import path from 'path';
    
    const upload = multer({ dest: path.join(__dirname, 'uploads/') });
    const app = express();
    
    app.post('/api/v1/garment/image/upload', upload.single('file'), (req, res) => {
      console.log(req.file, req.body);
      if (req.file) {
        res.sendStatus(201);
      } else {
        res.sendStatus(400);
      }
    });
    
    export { app };
    

    app.test.ts:

    import request from 'supertest';
    import multer from 'multer';
    import { NextFunction, Request, Response } from 'express';
    
    describe('69997349', () => {
      let app: typeof import('./app').app;
      beforeEach(async () => {
        jest.resetModules();
      });
      it('should return 201', async () => {
        const mockFile = { fieldname: 'myImage' } as Express.Multer.File;
        jest.doMock('multer', () => {
          const m = () => ({
            single: () => (req: Request, res: Response, next: NextFunction) => {
              req.body = { type: 'screenshots' };
              req.file = mockFile;
              return next();
            },
          });
          return m;
        });
        app = (await import('./app')).app;
        await request(app).post('/api/v1/garment/image/upload').send({ file: 'myImage' }).expect(201);
      });
    
      it('should return 400', async () => {
        jest.doMock('multer', () => {
          const m = () => ({
            single: () => (req: Request, res: Response, next: NextFunction) => {
              return next();
            },
          });
          return m;
        });
        app = (await import('./app')).app;
        await request(app).post('/api/v1/garment/image/upload').expect(400);
      });
    });
    

    测试结果:

     PASS  examples/69997349/app.test.ts (8.245 s)
      69997349
        ✓ should return 201 (297 ms)
        ✓ should return 400 (23 ms)
    
      console.log
        { fieldname: 'myImage' } { type: 'screenshots' }
    
          at examples/69997349/app.ts:10:11
    
      console.log
        undefined undefined
    
          at examples/69997349/app.ts:10:11
    
    Test Suites: 1 passed, 1 total
    Tests:       2 passed, 2 total
    Snapshots:   0 total
    Time:        9.428 s, estimated 10 s
    

    【讨论】:

    • 哦,非常感谢。我首先错过了app = (await import('./app')).app;,但在jest.doMock 之后添加了这个技巧。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-07
    • 2020-05-21
    • 2018-03-20
    • 2023-03-09
    • 1970-01-01
    • 1970-01-01
    • 2019-02-15
    相关资源
    最近更新 更多