You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

bcrypt.compare验证失败:Jest登录测试返回400错误求助

问题根源分析

你遇到的这个问题其实是全局变量被意外篡改导致的!

看你的beforeEach代码:

beforeEach(async () => {
    await User.deleteMany();
    const salt = await bcrypt.genSalt(10);
    const hashedPassword = await bcrypt.hash(existingUser.password, salt);
    // 这里直接修改了全局existingUser对象的password属性
    existingUser.password = hashedPassword;
    await User.create(existingUser);
});

existingUser是全局定义的对象,第一次执行beforeEach时,你把它的password改成了哈希值。等到后续测试用例(比如登录测试)触发beforeEach时,existingUser.password已经是哈希后的字符串了——你这时候再对这个哈希值进行二次哈希,然后存入数据库。

登录时你用原明文密码去和“哈希的哈希”做对比,bcrypt.compare自然会返回false,触发400错误。

解决方案

修改beforeEach,不要直接修改全局的existingUser,而是创建一个对象副本用来存入数据库:

beforeEach(async () => {
    await User.deleteMany();
    const salt = await bcrypt.genSalt(10);
    const hashedPassword = await bcrypt.hash(existingUser.password, salt);
    // 创建副本,保留原全局对象的密码不变
    const userToCreate = { ...existingUser, password: hashedPassword };
    await User.create(userToCreate);
});

这样每次执行beforeEach时,都是用existingUser的原始明文密码生成哈希,存入数据库的密码始终是正确的,登录时bcrypt.compare就能正常匹配了。

额外优化建议

另外,建议给登录控制器加个return,避免在返回错误响应后继续执行后续代码(虽然这不是当前问题的原因,但能避免潜在的双重响应bug):

if (!passwordValidation) {
    const error = new AppError({
        httpCode: HttpCode.BAD_REQUEST,
        description: 'Invalid Credentials'
    });
    logger.error(error);
    errorHandler.handleError(error, res);
    // 加个return终止函数执行
    return;
}

内容的提问来源于stack exchange,提问作者Anisul Haque

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 16:45:29