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
相关产品推荐
相关产品推荐

