如何在nodejs中使用jest模拟核心节点模块的特定功能

Sus*_*it 3 mongoose node.js express supertest jestjs

我想模拟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 });
      }
    };
Run Code Online (Sandbox Code Playgroud)

测试脚本:

    /* 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);
        }

  });
Run Code Online (Sandbox Code Playgroud)

我面临的问题是模拟我的“engineeremail_verification”中的加密实现(就在第 3 条评论下方)。我在代码的其他部分使用其他加密方法,我不想模拟它们。我只想用返回的模拟值来模拟加密模块的特定实现。我怎么做?感谢您解决我的问题。感谢任何形式的帮助。

sli*_*wp2 8

您可以使用jest.spyOn(object, methodName)单独进行模拟crypto.createHash

\n\n

例如

\n\n

app.js:

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

app.test.js:

\n\n
const app = require(\'./app\');\nconst request = require(\'supertest\');\nconst crypto = require(\'crypto\');\n\ndescribe(\'61368162\', () => {\n  it(\'should verify email\', async () => {\n    const hashMock = {\n      update: jest.fn().mockReturnThis(),\n      digest: jest.fn().mockReturnValueOnce(\'encrypt 123\'),\n    };\n    const createHashMock = jest.spyOn(crypto, \'createHash\').mockImplementationOnce(() => hashMock);\n    const logSpy = jest.spyOn(console, \'log\');\n    const engnr = { token: \'123\' };\n    const response = await request(app).put(`/api/engineer/confirm_mail/${engnr.token}`).send();\n    expect(createHashMock).toBeCalledWith(\'sha256\');\n    expect(hashMock.update).toBeCalledWith(\'123\');\n    expect(hashMock.digest).toBeCalledWith(\'hex\');\n    expect(logSpy).toBeCalledWith(\'encrypt 123\');\n    expect(response.statusCode).toBe(202);\n    expect(response.body).toMatchObject({ message: \'email verified\' });\n    createHashMock.mockRestore();\n    logSpy.mockRestore();\n  });\n\n  it(\'should restore crypto methods\', async () => {\n    const logSpy = jest.spyOn(console, \'log\');\n    const response = await request(app).put(\'/example/123\');\n    expect(jest.isMockFunction(crypto.createHash)).toBeFalsy();\n    expect(response.statusCode).toBe(200);\n    expect(logSpy).toBeCalledWith(expect.any(String));\n    logSpy.mockRestore();\n  });\n});\n
Run Code Online (Sandbox Code Playgroud)\n\n

集成测试结果与覆盖率报告:

\n\n
 PASS  stackoverflow/61368162/app.test.js (13.621s)\n  61368162\n    \xe2\x9c\x93 should verify email (44ms)\n    \xe2\x9c\x93 should restore crypto methods (5ms)\n\n  console.log node_modules/jest-environment-enzyme/node_modules/jest-mock/build/index.js:866\n    encrypt 123\n\n  console.log node_modules/jest-environment-enzyme/node_modules/jest-mock/build/index.js:866\n    a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3\n\n----------|---------|----------|---------|---------|-------------------\nFile      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s \n----------|---------|----------|---------|---------|-------------------\nAll files |   93.75 |      100 |     100 |   92.86 |                   \n app.js   |   93.75 |      100 |     100 |   92.86 | 12                \n----------|---------|----------|---------|---------|-------------------\nTest Suites: 1 passed, 1 total\nTests:       2 passed, 2 total\nSnapshots:   0 total\nTime:        15.707s\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n