【问题标题】:How to use Promises in Postman tests?如何在 Postman 测试中使用 Promise?
【发布时间】:2019-05-24 20:23:14
【问题描述】:

我需要在我的 Postman 测试中使用一些异步代码。

由于这是一个复杂的场景,我在一个非常简单的测试中使用以下代码重现了该场景:

let promiseNumber = 0;

function resolvedPromise() {
    return new Promise((resolve, reject) => {
        pm.sendRequest('https://postman-echo.com/get', (err, res) => {
            if (err) {
                console.log(err);
                reject();
            } else {
                console.log(`Resolved promise ${++promiseNumber}`);
                resolve();
            }
        });
    });
}

resolvedPromise()
    .then(resolvedPromise)
    .then(resolvedPromise)
    .catch(err => console.log(err));

控制台上的预期结果是:

Resolved promise 1
Resolved promise 2
Resolved promise 3

但我却收到:

Resolved promise 1

有没有办法让 Postman 提供 Promise 或异步代码?

【问题讨论】:

    标签: javascript asynchronous testing promise postman


    【解决方案1】:

    更新:原来的解决方案使用 2147483647 作为超时值,现在它被重构为使用 cmets 中建议的 Number.MAX_SAFE_INTEGER。

    我做了更多测试,发现在我使用 pm.sendRequest 后它总是停止工作。如果我尝试解决 Promise,它会起作用。

    查看this thread 似乎是一个已知错误。

    解决方法是在处理代码时只留下一个开放的超时。只要确保所有可能的路径都清除超时,否则呼叫将挂起 300000 年?

    // This timeout ensure that postman will not close the connection before completing async tasks.
    //  - it must be cleared once all tasks are completed or it will hang
    const interval = setTimeout(() => {}, Number.MAX_SAFE_INTEGER);
    
    let promiseNumber = 0;
    
    function resolvedPromise() {
        return new Promise((resolve, reject) => {
            pm.sendRequest('https://postman-echo.com/get', (err, res) => {
                if (err) {
                    console.log(err);
                    reject();
                } else {
                    console.log(`Resolved promise ${++promiseNumber}`);
                    resolve();
                }
            });
        });
    }
    
    resolvedPromise()
        .then(resolvedPromise)
        .then(resolvedPromise)
        .then(() => clearTimeout(interval))
        .catch(err => {
            console.log(err);
            clearTimeout(interval);
        });
    

    现在它打印出预期的结果:

    Resolved promise 1
    Resolved promise 2
    Resolved promise 3
    

    【讨论】:

    • 就我个人而言,我会使用Number.MAX_SAFE_INTEGER 而不是硬编码的2147483647。它不是同一个数字,但它是最大安全整数
    • 我尝试将它与 Number.MAX_SAFE_INTEGER 一起使用,但没有成功。如果你用任何超过 1000 的东西替换它,它就可以工作。
    • 每个请求似乎需要 200 到 500 毫秒之间的时间。所以是的,我可以确认之前的评论建议任何超过 1000。您链接的请求越多,clearTimeout 所需的值就越高。我也玩过上限,发现10亿有效,但不是100亿(ms)。
    • @seemcat 同意,这非常重要!不要使用Number.MAX_SAFE_INTEGER!!使用 100000 之类的东西。
    【解决方案2】:

    除了Felipe的回答,我想多分享一点我使用Postman的经验。

    由于我需要从 pm.sendRequest 的响应中提取一些值并将它们用于进行主要调用(例如查询字符串)和/或在 Tests 部分中,我在预请求脚本部分并在 Postman 环境变量中设置值。

    我发现重要的一点是,我必须将所有设置变量的代码(例如pm.environment.set(k, v))放在clearTimeout(timeout) 之前。否则,如果我反其道而行之,pm.environment.set(k, v) 代码仍然会运行,但不会更新环境变量的值。


    以下是 Postman v8.5.1 的示例。

    主调用

    期望从环境变量中获取TEST

    GET http://google.com/{{TEST}}
    

    预请求脚本

    期望设置TEST环境变量,其值来自多个API的结果。在这个例子中,我只使用了Promise.all返回的最后一个值。

    // make sure you do NOT use Number.MAX_SAFE_INTEGER !!
    const timeout = setTimeout(() => {}, 100000);
    
    const promise = () => {
        return new Promise((resolve, reject) => {
            console.log('Calling');
            pm.sendRequest('https://jsonplaceholder.typicode.com/todos/' + _.random(1, 100), (err, res) => {
                console.log('run');
                if (err) {
                    reject();
                } else {
                    resolve(res.json());
                }
            });
        });
    }
    
    Promise.all([
        promise(),
        promise(),
        promise(),
        promise(),
        promise(),
        promise(),
        promise(),
        promise(),
    ]).then(values => {
        console.log('All done');
        const exampleValue = values[values.length-1].id;
        console.log("Last ID: " + exampleValue);
    
        clearTimeout(timeout);
    
        // move this line before clearTimeout to fix TEST being undefined
        pm.environment.set("TEST", exampleValue);
    });
    

    测试

    期望打印TEST 环境变量。

    // you get undefined if pm.environment.set is run after clearTimeout
    // you get correct value if pm.environment.set is run before clearTimeout
    console.log(pm.variables.get("TEST"));
    

    如何测试

    将 URL 和所有脚本复制到 Postman 后,打开 Console 并点击 Send。查看被调用的实际 URL 的查询字符串(即GET http://google.com/%7B%7BTEST%7D%7D)。然后重新排列 cmets 中提到的代码并再次单击 Send。这次一切都应该按预期进行。

    【讨论】:

    • 嗨!我刚刚发现自己处于与这个完全一样的场景中。尝试实施此解决方案,即使它在从 Postman 运行时有效,但在我使用 newman 执行测试时却无效。我的变量(将其设置为全局、集合、环境或只是变量)没有设置...知道它是否与 Postman 版本有关吗?我在 9.0.3(最新)
    猜你喜欢
    • 2013-02-10
    • 2020-04-27
    • 2019-12-18
    • 1970-01-01
    • 2018-07-06
    • 1970-01-01
    • 2017-08-15
    • 2022-09-30
    • 2019-09-30
    相关资源
    最近更新 更多