node.js - 如何在测试套件中仅模拟一次函数?

标签 node.js mocking jestjs

我正在为一个项目编写集成测试。在一个测试套件中,我在多个测试中调用注册端点。大多数时候,我想测试给定某些 req 参数后 registerUser 函数的实际响应是什么。

这一切都工作正常,除了我还想测试 registerUser 函数抛出错误时会发生什么。我知道我可以在测试套件之上模拟 registerUser 函数,但这会影响所有测试。我尝试使用 jest.mockjest.spyOn 但我还无法让它工作。

如何模拟一次 registerUser 函数的响应并在之后恢复它,这样它就不会影响套件中的其他测试?

authController.js

router.post('/register', async (req, res) => {
    try {
        const response = await registerUser(req);
        res.status(HttpStatus.OK).json({ response });
    } catch (err) {
        res.status(HttpStatus.INTERNAL_SERVER_ERROR).json({ err });
    }
});

authController.test.js

const faker = require('faker');
const HttpStatus = require('http-status-codes');
const authService = require('../services/authService');

// -- Tests where the response of the registerUser function are not mocked are here -- //

it('Gives a status code 500 when an unexpected error is thrown', async () => {
    const registerUserMock = jest.spyOn(authService, "registerUser");
    registerUserMock.mockReturnValue(() => new Error('Oh snap! Something went wrong.'));

    const res = await agent.post('/register')
        .send({
            email: faker.internet.email(),
            firstname: faker.name.firstName(),
            lastname: faker.name.lastName(),
            password: '123',
            reTypedPassword: '123',
        });

    expect(res.statusCode).toBe(HttpStatus.INTERNAL_SERVER_ERROR);
    
    registerUserMock.mockRestore();
});

// -- more tests -- //

最佳答案

最简单的方法是

  1. 将应在套件中使用相同模拟响应的测试分组(描述)
  2. 模拟该套件的 beforeAll Hook 中的响应并保存模拟实例
  3. 恢复该套件的 afterAll Hook 中的原始实现。
describe('tests with successful auth result', () => {

    let authSpy;

    beforeAll(() => {
        authSpy = jest.spyOn(authService, "registerUser").mockReturnValue(...);
    });

    afterAll(() => {
        authSpy.mockRestore();
    });

    // tests using successful result

});

describe('tests with failing auth result', () => {
    // same but with different spy result
});

注意两件重要的事情:

  • 您需要对从 mockReturnValue 返回的模拟实例调用 mockRestore,而不是初始 spy 值
  • 最好在 beforeEach/beforeAll 中设置模拟并在 afterEach/afterAll 中恢复它,因为如果您直接在测试中设置和恢复它(it),那么如果测试失败,spy 仍然无法恢复,并且可能会影响后续测试!

关于node.js - 如何在测试套件中仅模拟一次函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63768068/

相关文章:

javascript - 如何使用其他站点的登录信息发出 JavaScript 请求

c# - 如何用最小起订量模拟 System.Xml.XmlWriter.WriteAttributeString()?

node.js - Actor 错误: Cast to ObjectId failed for value "login" at path \"_id\" for model "users"

mysql - pretty-print Node.js MySQL SELECT 查询对控制台/变量的响应

unit-testing - 在 Spock 中模拟父类(super class)

javascript - 模拟从另一个文件导入但仍返回模拟值

javascript - 使用 Jest : Can I mock an ES6 class 对 JS 脚本进行单元测试

javascript - 如果使用 Ramda reduce 但使用 native 则 Jest 测试失败

javascript - 如何阻止错误 'read ECONNRESET' 的发生

python - python mock __init__() 返回伪类的正确方法