单元测试:测试内部承诺

时间:2016-10-31 12:44:30

标签: javascript unit-testing mocha es6-promise

我已经在网上搜索了一段时间,但我还没有找到答案。

我们说我们正在测试以下内容:

function p() {
    return Promise.resolve(1);
}

class Sample {
    constructor() {
        this.stuff = 2;
    }

    sample () {
        p().then((data) => {
            this.stuff = data;
        });

        //more stuff
    }
}

module.exports = {Sample};

我们如何检查,最终填充this.stuff而不返回所述承诺?

这是我迄今为止所做的事情:

let expect = require('chai').expect;
let sinon = require('sinon');

let Sample = require('./source.js').Sample;

describe('stuff', function () {
    it('test2', function() {
        let sample = new Sample();

        return Promise.resolve(sample.sample())
            .then(() => {
                expect(sample.stuff).to.be.eql(2);
            });
    });
});

其中,每个then获得下一个标记(如果我们的示例中有多个then,我们在测试中也需要多个then。< / p>

(在您说process.nextTick之前,我想让它在浏览器中使用karma-mocha运行)

提前致谢!

2 个答案:

答案 0 :(得分:0)

如果重新构建代码,可以很容易地测试它,以支持可测试性。

执行此操作的一种方法是为对象实例化采用可选的p接口。该值可以默认为您定义的p,但允许测试创建虚假对象并验证您的Sample是否正确操作。

function p() {
    return Promise.resolve(1);
}

class Sample {
    constructor(pFn) {
        this.stuff = 2;
        this.p = pFn || p;
    }

    sample () {
        this.p().then((data) => {
            this.stuff = data;
        });

        //more stuff
    }
}

这将允许您为单元测试提供同步执行的类似承诺的对象。

答案 1 :(得分:0)

一种方法是定期检查设定值。

it('test2', function(done) {
    let sample = new Sample();
    let assert = function() {
        if(sample.stuff === 2) {
            done();
        } else {
            setTimeout(assert, 0);
        }
    };

    sample.sample();
    assert();
});

它不是最漂亮的,并且在失败时不会给出最好的错误信息,但它会起作用。如果sample.stuff在几秒钟内未设置为2(我认为默认为3秒),则测试将失败,因为未及时调用done()

另一种可能的选择是让测试用替换器替换stuff。然后你可以在expect()上设置。

it('test2', function(done) {
    let sample = new Sample();
    Object.defineProperty(sample, 'stuff', { set: function (value) {
        expect(value).to.be.eql(2);
        done();
    }});

    sample.sample();
});