0

我目前正在用 JavaScript 制作一个小型服务器,作为学习过程的一部分,我正在为这些函数编写单元测试。不幸的是,我在处理承诺的某个测试中遇到了重大困难。下面是路由器模块,带有单独的handlePUT函数,方便测试。

const express = require('express');
const service = require('../service/user.service');

const dutyStatusRouter = express.Router();
const output = console;

function handlePUT(req, res) {
    service.updateUserStatus()
        .then((fulfilled) => {
            res.status(fulfilled);
            res.send();
        })
        .catch(() => {
            res.status(500);
            res.send();
        });
}

dutyStatusRouter.route('/').put(handlePUT);

updateUserStatus 函数基本上在数据库中切换布尔值,看起来有点像这样:

function updateUserStatus() {
    return new Promise((resolve, reject) => {
        if (…) {
            resolve(201);
        } else if (…) {
            resolve(200);
        } else {
            reject();
        }
    });
}

至于单元测试,我使用 mocha/chai 和 proxyquire 来创建模拟 updateUserStatus。

const chai = require('chai');
const sinon = require('sinon');
const proxyquire = require('proxyquire');

const serviceStub = {};

describe('=== Unit test ===', () => {
    it('Handle PUT test: promise kept', async () => {
        const dutyStatusRouter = proxyquire('../../router/duty-status.router', {
            '../service/user.service': serviceStub,
        });
        serviceStub.updateUserStatus = () => {
            return new Promise((resolve, reject) => {
                resolve(200);
            });
        };
        const res = {
            status: sinon.fake(),
            send: sinon.fake(),
        };
        await dutyStatusRouter.handlePUT({}, res);
        chai.assert(res.status.calledOnceWith(200));
    });
});

每当我尝试运行单元测试时,都会收到错误消息Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.。如果我尝试添加done()它仍然会通过给出错误消息而失败Error: Resolution method is overspecified. Specify a callback *or* return a Promise; not both.

4

1 回答 1

1

找到了一个可行的解决方案,所以我在这里添加它:

const chai = require('chai');
const sinon = require('sinon');
const proxyquire = require('proxyquire');

const serviceStub = {};
const dutyStatusRouter = proxyquire('../../router/duty-status.router', {
    '../service/user.service': serviceStub,
});

describe('=== Unit test ===', () => {
    it('Handle PUT test: promise kept', (done) => {
        serviceStub.updateUserStatus = sinon.stub().resolves(200);
        const res = {
            status: sinon.fake(),
            send: sinon.fake(),
        };
        dutyStatusRouter.handlePUT({}, res).then(() => {
            chai.assert(res.status.calledWith(200));
            done();
        });
    });
});

注意:我稍微更改了 handlePUT 函数,现在看起来像这样(我只是添加了一个返回):

function handlePUT(req, res) {
    return service.updateUserStatus()
        .then((fulfilled) => {
            output.log('Promise fulfilled');
            res.status(fulfilled);
            res.send();
        })
        .catch(() => {
            output.log('Promise unfulfilled');
            res.status(500);
            res.send();
        });
}
于 2018-09-05T10:15:00.887 回答