如何使用Jest模拟模块的功能仅用于特定测试

时间:2017-11-28 20:11:46

标签: unit-testing typescript jestjs

我需要模拟依赖的功能,但仅限于特定的测试用例。在我的其他测试中,我想保持模块不变。我也在嘲笑其他模块。那些需要保持嘲笑。

我尝试了多种方法,因为我已经问过这个问题的多种变体,但由于我需要在没有嘲笑的情况下使用原始模块,所以其他解决方案似乎都没有用......

这是我需要的一个例子

// app.ts
import * as moduleA from 'moduleA';

...

app.post('/signup', async (req, res) => {
   ...
   const hashed = await moduleA.hash(req.body.password);
   ...
});

export default app;


// app.test.ts

// some mocks
jest.mock('./database', () => ({ ... }));
...

import * as request from 'supertest';
import app from './app;

...

describe('A', () => {
    test('Those should work', async () => {
        const response = await request(app).post('/signup').send({ password: 'pw' });
        expect(response.status).toBe(200);
        ...
    });
    // many other tests

    test('I need to force hash to crash here', async () => {
        // mock moduleA.hash only for this test
        const response = request(app).post('/signup').send({ password: 'pw' });
        expect(response.status).toBe(500);
    });

    test('moduleA.hash should be back to its default function', async () => {
        // request(app) and moduleA.hash will work properly, not mocked
        // ./database stays mocked
    });
});

1 个答案:

答案 0 :(得分:0)

您可以使用jest.spyOn()模拟hash的{​​{1}}方法,并使用moduleA.mockRestore()方法还原到原始实现。

这是解决方案:

hash

app.ts

import express from 'express'; import bodyParser from 'body-parser'; import * as moduleA from './moduleA'; const app = express(); app.use(bodyParser.urlencoded({ extended: false })); app.use(bodyParser.json()); app.post('/signup', async (req, res) => { try { const hashed = await moduleA.hash(req.body.password); console.log(hashed); res.sendStatus(200); } catch (error) { res.sendStatus(500); } }); export default app;

moduleA.ts

export const hash = async (data: string) => { return 'real hashed value'; };

app.spec.ts

覆盖率100%的单元测试结果:

import app from './app';
import request from 'supertest';
import * as moduleA from './moduleA';

describe('app', () => {
  test('Those should work', async () => {
    const response = await request(app)
      .post('/signup')
      .send({ password: 'pw' });
    expect(response.status).toBe(200);
  });

  test('I need to force hash to crash here', async () => {
    const mockedError = new Error('hash error');
    const hashSpy = jest.spyOn(moduleA, 'hash').mockRejectedValueOnce(mockedError);
    const response = await request(app)
      .post('/signup')
      .send({ password: 'pw' });
    expect(response.status).toBe(500);
    expect(moduleA.hash).toBeCalledWith('pw');
    hashSpy.mockRestore();
  });

  test('moduleA.hash should be back to its default function', async () => {
    const logSpy = jest.spyOn(console, 'log');
    const response = await request(app)
      .post('/signup')
      .send({ password: 'pw' });
    expect(response.status).toBe(200);
    expect(logSpy).toBeCalledWith('real hashed value');
  });
});

以下是完整的演示:https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/47540126