Jest mock并不总是在异步测试中工作



我有一个函数,我想用Jest测试它。

function handleRegister() {
return (req, res) => {

try {
const credentials = {
login: req.body.email,
password: req.body.password
}

res.status(201).send({ msg: 'User registration achieved successfully' })  //LINE 10
res.status(201).send({ msg: 'User registration achieved successfully' })  //LINE 11

auth.register(credentials, (err, result) => {
console.log('register', auth.getUsers())

if (result.status === 201) {
res.status(201).send({ msg: 'User registration achieved successfully' })  //LINE 17
console.log('User registration achieved successfully')
}
})
} catch(err) {
}
}}
我的测试代码是:
test('should return status 201 and msg', done => {
try {
const fun = handlers.handleRegister()
const res = {
status: jest.fn().mockReturnThis(),
send: function () {
done()
}
}

fun({ body: { email: 'a', password: 'a' } }, res)
expect(res.status).toBeCalledWith(201)
} catch(err) {
done(err)
}
})

问题是函数handlerRegister第10行和第11行被正确执行,但在第17行我得到了一个错误:

/home/anna/Desktop/dev/exampleShop/backend/handlers.js:149
res.status(201).send({
^
TypeError: Cannot read property 'send' of undefined
at auth.register (/home/anna/Desktop/dev/exampleShop/backend/handlers.js:149:26)
at addAccountToDB (/home/anna/Desktop/dev/exampleShop/backend/auth.js:69:7)
at addAccountToDB (/home/anna/Desktop/dev/exampleShop/backend/auth.js:81:3)
at hashPassword (/home/anna/Desktop/dev/exampleShop/backend/auth.js:68:5)
at AsyncWrap.crypto.scrypt (/home/anna/Desktop/dev/exampleShop/backend/auth.js:87:5)
at AsyncWrap.wrap.ondone (internal/crypto/scrypt.js:43:48)

如果我使用js,而不是模拟属性res,如:

const res = {
status: function(){return this},
send: function () {
done()
}
}
}

那么我就没有这个错误了。

谁能告诉我怎么了?

有一个范围问题。在调用res.send()的地方没有定义res,因为res是在try块内部定义的。

将expect语句移到try中,或者将res定义在与expect语句相同的作用域中。

也不能在非模拟函数的函数上调用.toBeCalledWith。因此,请注意,我已将res.send定义为模拟函数,并在expect语句的末尾调用done()

test('should return status 201 and msg', done => {
try {
const fun = handlers.handleRegister()
// res only exists inside of the `try`
const res = {
status: jest.fn().mockReturnThis(),
send: jest.fn() // << is now a mock function
}
fun({ body: { email: 'a', password: 'a' } }, res)
expect(res.status).toBeCalledWith(201)
// here `res.send` is now defined, and you can use `toBeCalledWith`
expect(res.send).toBeCalledWith({ msg: 'User registration achieved successfully' })
done();
} catch(err) {
done(err)
}
})

最新更新