测试承诺导致未定义的值

testing promises causing undefined values

本文关键字:未定义 承诺 测试      更新时间:2023-09-26

当我测试我的代码时,我得到这个错误:

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

getStatusCode不返回任何东西。它应该返回一个承诺:

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

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

它甚至更复杂,因为规范是异步的,在规范完成之前有几个承诺应该等待。应该是像

这样的东西
    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]);
        }
    });

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

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