简体   繁体   English

如何在 Postman 测试中使用 Promises?

[英]How to use Promises in Postman tests?

I need to use some async code in my Postman test.我需要在 Postman 测试中使用一些异步代码。

As it's a complex scenario I've reproduced the scenario in a very simple test with the following code:由于这是一个复杂的场景,我使用以下代码在一个非常简单的测试中重现了该场景:

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

The expected result on the console would be:控制台上的预期结果是:

Resolved promise 1
Resolved promise 2
Resolved promise 3

But instead I receive:但相反,我收到:

Resolved promise 1

Is there a way to make Promises or async code available at Postman?有没有办法在 Postman 上提供 Promise 或异步代码?

UPDATE : The original solution used 2147483647 as timeout value, now it was refactored to use Number.MAX_SAFE_INTEGER as suggested in the comments.更新:原始解决方案使用 2147483647 作为超时值,现在按照评论中的建议重构为使用 Number.MAX_SAFE_INTEGER。

I did some more tests and realize that it always stop working after I use pm.sendRequest.我做了一些更多的测试,并意识到在我使用 pm.sendRequest 后它总是停止工作。 If I try to resolve the Promise it works.如果我尝试解决 Promise,它会起作用。

Seems a known bug looking at this thread .这个线程似乎是一个已知的错误。

The workaround for it would be only leave an open timeout while processing the code.它的解决方法是在处理代码时只留下一个开放的超时。 Just ensure all possible paths clear the timeout or the call will hang for 300000 years 😀只需确保所有可能的路径清除超时,否则呼叫将挂起 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);
    });

Now it prints the expected result:现在它打印出预期的结果:

Resolved promise 1
Resolved promise 2
Resolved promise 3

In addition to Felipe's answer, I'd like to share a little bit more with my experience in using Postman.除了 Felipe 的回答,我还想多分享一点我使用 Postman 的经验。

As I need to extract some values from the responses of pm.sendRequest and use them in making the main call (eg query string) and/or in the Tests section, I run the script in the Pre-request Script section and set the values in Postman environment variables.由于我需要从pm.sendRequest的响应中提取一些值并将它们用于进行主要调用(例如查询字符串)和/或在测试部分中,我在预请求脚本部分运行脚本并设置值在 Postman 环境变量中。

One important point that I find out is that I must put all the code of setting variables (eg pm.environment.set(k, v) ) before clearTimeout(timeout) .我发现的一个重要点是我必须在clearTimeout(timeout)之前放置所有设置变量的代码(例如pm.environment.set(k, v) clearTimeout(timeout) Otherwise, if I do it the other way round, the pm.environment.set(k, v) code will still be run but the value of the environment variable will not be updated.否则,如果我pm.environment.set(k, v)做, pm.environment.set(k, v)代码仍将运行,但不会更新环境变量的值。


Below is an example with Postman v8.5.1 .以下是 Postman v8.5.1的示例。

Main call主叫

Expect to get TEST from the environment variables.期望从环境变量中获得TEST

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

Pre-request Script预请求脚本

Expect to set the TEST environment variable of which the value comes from the results of multiple APIs.期望设置TEST环境变量,其值来自多个API的结果。 In this example, I just use the last value returned from Promise.all .在这个例子中,我只使用从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);
});

Tests测试

Expect to print the TEST environment variable.期望打印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"));

How to test如何测试

After copying the URL and all the scripts to Postman, open up Console and click Send .将 URL 和所有脚本复制到 Postman 后,打开Console并单击Send Take a look at the query string of the actual URL being called (ie GET http://google.com/%7B%7BTEST%7D%7D ).查看被调用的实际 URL 的查询字符串(即GET http://google.com/%7B%7BTEST%7D%7D )。 Then rearrange the code as mentioned in the comments and click Send again.然后重新排列注释中提到的代码,然后再次单击发送 This time everything should work as expected.这次一切都应该按预期工作。

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

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