繁体   English   中英

测试承诺链与异步等待 [mocha/chai/sinon]

[英]Testing promise chains vs async await [mocha/chai/sinon]

所以我是测试新手,并且已经设置了一个模拟数据库调用失败的方法的基本测试(对不起,如果我的术语不太正确)

我正在使用 sequelize,所以Job是一个模型,而findAndCountAll是一个相关的方法。

it('Should throw a 500 error if accessing the DB fails', () => {
    sinon.stub(Job, 'findAndCountAll');
    Job.findAndCountAll.throws();

    const req = {
        query: {
            index: 0,
            limit: 10,
            orderField: 'createdAt',
            order: 'DESC'
        }
    };

    adminController.getJobs(req, {}, () => {}).then(result => {
            expect(result).to.be.an('error');
            expect(result).to.have.property('statusCode', 500);

            done();
        })

    Job.findAndCountAll.restore();
})

我的问题是我的大部分代码都是使用承诺链编写的:

exports.getJobs = (req, res, next) => {
    const index = req.query.index || 0;
    const limit = req.query.limit || 10;
    const orderField = req.query.orderField || 'createdAt';
    const order = req.query.orderDirection || 'DESC';
 
    Job.findAndCountAll({
        // ...arguments
    })
    .then(results => {
        res.status(200).json({ jobs: results.rows, total: results.count });
        return // Attempted to add a return statement to enter the .then() block in the test
    })
    .catch(err => {
        if(!err.statusCode) err.statusCode = 500;

        next(err);
        return err; // Attempted to return the error to enter the .then() block in the test
    });

这不起作用,我的(不必要的)返回语句也无济于事。

但是,使用async await重写方法确实有效(见下文)。 但是我想避免重写我的所有代码,如果能理解这里的区别会很好。

我最好的猜测是,与其让 sinon 存根抛出错误,不如让它拒绝承诺? 我只是不完全确定这是否正确,或者如何实现它。 我有点绊倒文档并不真正知道

任何帮助表示赞赏,

谢谢,

缺口

exports.getJobs = async(req, res, next) => {
    const index = req.query.index || 0;
    const limit = req.query.limit || 10;
    const orderField = req.query.orderField || 'createdAt';
    const order = req.query.orderDirection || 'DESC';

    try {
        const results = await Job.findAndCountAll({ //...params });

        // ... 

        res.status(200).json({ jobs: results.rows, total: results.count });
        return;
    } catch(err) {
        if(!err.statusCode) err.statusCode = 500;
        next(err);
        return err;
    } 
};

所以我想我找到了答案:

sinon 中的存根需要返回一个被拒绝的承诺,而不是抛出一个错误:

sinon.stub(Job, 'findAndCountAll');
Job.findAndCountAll.rejects();

Afaik 这是因为你不能真正在异步代码中抛出错误。

您正在测试的方法中的 Promise 链(在我的例子中是“getJobs”),需要返回该承诺。

所以代替

  Job.findAndCountAll({
            // ...arguments
        })
        .then(results => {
            res.status(200).json({...});
            return;
        })
        .catch(err => {
            if(!err.statusCode) err.statusCode = 500;

            next(err);
            return err;
        });

采用

   const results = Job.findAndCountAll({
            // ...arguments
        })
        .then(results => {
            res.status(200).json({...});
            return;
        })
        .catch(err => {
            if(!err.statusCode) err.statusCode = 500;

            next(err);
            return err;
        });
   return results;

此外,测试中的异步函数需要返回或等待,以便 mocha 知道等待。 使用done()对我不起作用:

const result = await adminController.getJobs(req, {}, () => {});

expect(result).to.be.an('error');
expect(result).to.have.property('statusCode', 500);

Job.findAndCountAll.restore();

希望能帮助某人

**编辑:如下所述,我忘记将done作为参数传递,这就是该方法不起作用的原因

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM