简体   繁体   English

单元测试:测试内部承诺

[英]Unit tests: Testing inner Promise

I've been searching the web for a while and I've yet to find the answer to this. 我已经在网上搜索了一段时间,但尚未找到答案。

Let's say we're testing the following: 假设我们正在测试以下内容:

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

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

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

        //more stuff
    }
}

module.exports = {Sample};

How could we check that, eventually this.stuff is populated without returning said promise? 我们如何检查该结果,最终填充this.stuff而不返回上述承诺?

This is what I've been able to do until now: 到目前为止,这是我能够做的:

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);
            });
    });
});

In which, each then gets the next tick (if we had multiple then s in our sample we'd also need multiple then s in our test). 其中,每个then得到一个信用(如果我们有多个then是我们的样本中,我们想也需要多个then S IN我们的测试)。

(And before you say process.nextTick , I want this to run in the browser with karma-mocha) (并且在您说process.nextTick之前,我希望它可以通过karma-mocha在浏览器中运行)

Thanks in advance! 提前致谢!

This could be easily tested if the code was restructured, to support testability. 如果代码经过重组以支持可测试性,则可以很容易地对其进行测试。

One way to do this would be to take an optional p interface for the object instantiation. 一种方法是为对象实例化使用可选的p接口。 The value could default to your defined p but would allow for a test to create a fake object and verify that your Sample operates on it correctly. 该值可以默认为您定义的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
    }
}

This would allow you to provide a promise-like object, for your unit test, that executes synchronously. 这将允许您为单元测试提供一个类似promise的对象,该对象可以同步执行。

One way would be to periodically check for the set value. 一种方法是定期检查设置值。

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

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

It's not the prettiest, and won't give the best error message on a failure, but it would work. 它不是最漂亮的,并且不会在失败时给出最佳的错误消息,但是它可以工作。 If sample.stuff isn't set to 2 within a couple seconds (I think 3 seconds is the default) then the test will fail because done() was not called in time. 如果没有在两秒钟内将sample.stuff设置为2 (我认为默认值为3秒),则测试将失败,因为未及时调用done()


Another possible option is to have the test replace stuff with a setter. 另一个可能的选择是让测试用设置器替换stuff Then you can expect() on set. 然后您可以在set上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();
});

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

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