【问题标题】:testing promises causing undefined values测试承诺导致未定义的值
【发布时间】:2016-08-22 02:59:27
【问题描述】:

我在测试代码时收到此错误:

1) Sourcerer Testing:  getStatusCode :
     Error: Expected undefined to equal 200

我不确定为什么在我的测试中得到undefined,但是当我运行代码时我得到200。可能是因为没有正确处理promises

Test code:

import expect from 'expect';
import rp from 'request-promise';
import Sourcerer from './sourcerer';


describe("Sourcerer Testing: ", () => {
    let sourcerer = new Sourcerer(null);
    const testCases = {
        "https://www.google.com": 200,
        // "www.google.com":
    };

    describe("getStatusCode", () => {
        it("", () => {
            for (let testCase in testCases) {
                sourcerer.setSourcererUrl(testCase);
                expect(sourcerer.url).toEqual(testCase);
                expect(sourcerer.getStatusCode()).toEqual(testCases[testCase]);
            }
        });
    });
});

代码:

import rp from 'request-promise';

export default class Sourcerer {
    constructor(url) {
        this.options = {
            method: 'GET',
            url,
            resolveWithFullResponse: true
        };
        this.payload = {};
    }

    setSourcererUrl(url) {
        this.url = url;
    }

    getSourcererUrl() {
        return this.url;
    }

    analyzeSourcePage() {
        rp(this.options).then((res) => {
            console.log(res);
        }).catch((err) => {
            console.log("ERROR");
            throw(err);
        });

    }

    getStatusCode() {
        rp(this.options).then((res) => {
            console.log(res.statusCode);
            return res.statusCode;
        }).catch((err) => {
            console.log("STATUS CODE ERROR");
            return 0;
        });
    }
}

【问题讨论】:

    标签: javascript promise ecmascript-6 mocha.js


    【解决方案1】:

    getStatusCode 不返回任何内容。它应该返回一个承诺:

    getStatusCode() {
        return rp(this.options)...
    }
    

    在这种情况下,规范将失败,因为它期望 promise 对象等于 200。

    这更加复杂,因为规范是异步的,并且在规范完成之前应该等待几个 Promise。应该是这样的

        it("", () => {
            let promises = [];
            for (let testCase in testCases) {
                sourcerer.setSourcererUrl(testCase);
                let statusCodePromise = sourcerer.getStatusCode()
                .then((statusCode) => {
                    expect(sourcerer.url).toEqual(testCase);
                    expect(statusCode).toEqual(testCases[testCase]);
                })
                .catch((err) => {
                    throw err;
                });
                promises.push(statusCodePromise);
            }
    
            return promises;
        });
    

    co 提供了一个很棒的替代 Promise.all 的流量控制方案:

        it("", co.wrap(function* () {
            for (let testCase in testCases) {
                sourcerer.setSourcererUrl(testCase);
                expect(sourcerer.url).toEqual(testCase);
                let statusCode = yield sourcerer.getStatusCode();
                expect(statusCode).toEqual(testCases[testCase]);
            }
        });
    

    【讨论】:

    • @Liondancer 还应该注意的是,规范不一定是异步的。可以模拟 http 请求(例如使用 nock),而 Sinon 和 Jasmine 都提供模拟计时器功能并使规范同步的方法。
    【解决方案2】:

    免责声明:我不会在单个 it() 中运行 for 循环,因为我想知道哪个迭代失败了。当然,有办法实现这一目标,但那是另一回事了。此外,这在很大程度上取决于您的测试运行程序,但这里有一些我认为有用的经验法则。

    但是对于您所要求的,在解决承诺之前,测试不应该评估。有时(例如在 mocha 中),这意味着从 it() 内部函数返回承诺。有时,这意味着获得一个 done 函数并在您准备好进行测试评估时调用它。如果您提供有关您的测试框架的更多信息,我可能会提供帮助(其他人肯定会)

    【讨论】:

      猜你喜欢
      • 2014-05-29
      • 2016-12-10
      • 1970-01-01
      • 2022-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-19
      相关资源
      最近更新 更多