如何在Node.js中使用Jest模拟核心节点模块的特定功能

时间:2020-04-22 14:53:22

标签: node.js express mongoose jestjs supertest

我想模拟nodejs的“ crypto”模块的特定方法。

我正在使用jest框架测试代码中的端点。

电子邮件验证的端点代码如下:

/ * engnr_cntrlr.js * /

exports.engineeremail_verifcation = async(req, res) => {
    try {

        // 3. i want to mock the next statement and return a mock-value to hashedToken variable

        const hashedToken = crypto
          .createHash('sha256')
          .update(req.params.token)
          .digest('hex');

        const engnr = await Engineer.findOne({
         engnrToken : hashedToken
        }).orFail(new Error ('engnr not found'));

        engnr.emailVerify = true 
        await engnr.save()

        return res.status(202).send({ message: 'email verified' });

      } catch (error) {
        res.status(400).send({ error: error.message });
      }
    };

测试脚本:

    /* tests/engineer.test.js */

     test('engineer verifies his email', async done => {

           // 1. i am fetching an engnr using an email id

          engnr = await Engineer.findOne({
               email: engineerOne.email
        }); 

        try {
          const response = await request(app)
            .put(`/api/engineer/confirm_mail/${engnr.token}`) //2. i am sending a hashed token as a req.params
            .send();

          expect(response.statusCode).toBe(202);
          expect(response.body).toMatchObject({
            message: 'email verified'
          });

          done();
        } catch (error) {
          done(error);
        }

  });

我面临的问题是在我的“ engineeremail_verification”中模拟加密实现(仅在注释3下方)。我在代码的其他部分中使用了其他加密方法,并且我不想模拟它们。我只想模拟该加密模块的特定实现,并返回模拟值。我怎么做?谢谢您回答我的问题。感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

您可以使用jest.spyOn(object, methodName)分别模拟String

例如

crypto.createHash

app.js

const crypto = require('crypto'); const express = require('express'); const app = express(); app.put('/api/engineer/confirm_mail/:token', async (req, res) => { try { const hashedToken = crypto.createHash('sha256').update(req.params.token).digest('hex'); console.log(hashedToken); return res.status(202).send({ message: 'email verified' }); } catch (error) { res.status(400).send({ error: error.message }); } }); app.put('/example/:token', async (req, res) => { const hashedToken = crypto.createHash('sha256').update(req.params.token).digest('hex'); console.log(hashedToken); res.sendStatus(200); }); module.exports = app;

app.test.js

具有覆盖率报告的集成测试结果:

const app = require('./app');
const request = require('supertest');
const crypto = require('crypto');

describe('61368162', () => {
  it('should verify email', async () => {
    const hashMock = {
      update: jest.fn().mockReturnThis(),
      digest: jest.fn().mockReturnValueOnce('encrypt 123'),
    };
    const createHashMock = jest.spyOn(crypto, 'createHash').mockImplementationOnce(() => hashMock);
    const logSpy = jest.spyOn(console, 'log');
    const engnr = { token: '123' };
    const response = await request(app).put(`/api/engineer/confirm_mail/${engnr.token}`).send();
    expect(createHashMock).toBeCalledWith('sha256');
    expect(hashMock.update).toBeCalledWith('123');
    expect(hashMock.digest).toBeCalledWith('hex');
    expect(logSpy).toBeCalledWith('encrypt 123');
    expect(response.statusCode).toBe(202);
    expect(response.body).toMatchObject({ message: 'email verified' });
    createHashMock.mockRestore();
    logSpy.mockRestore();
  });

  it('should restore crypto methods', async () => {
    const logSpy = jest.spyOn(console, 'log');
    const response = await request(app).put('/example/123');
    expect(jest.isMockFunction(crypto.createHash)).toBeFalsy();
    expect(response.statusCode).toBe(200);
    expect(logSpy).toBeCalledWith(expect.any(String));
    logSpy.mockRestore();
  });
});

源代码:https://github.com/mrdulin/react-apollo-graphql-starter-kit/tree/master/stackoverflow/61368162