使用loadimpact k6对使用oauth令牌进行授权的API进行负载测试

时间:2019-11-15 15:10:52

标签: postman k6 postman-pre-request-script

我正在尝试使用loadimpact k6对API(GET方法)进行负载测试,这需要oauth令牌进行授权才能获得成功的响应。我已经有一个邮递员收集文件,可以通过运行请求前脚本来完成此任务。预先请求脚本将向授权服务器请求令牌,然后将令牌填充到环境变量中。我使用“邮递员到LoadImpact转换器”生成了k6脚本,但它没有任何帮助。该脚本无法获取访问令牌。

从转换器生成的脚本如下:

// Auto-generated by the Load Impact converter

import "./libs/shim/core.js";

export let options = { maxRedirects: 4 };

const Request = Symbol.for("request");
postman[Symbol.for("initial")]({
  options,
  collection: {
    currentAccessToken: "",
    "Client-Id": "",
    "Client-Secret": "",
    "Token-Scope": "",
    "Grant-Type": "client_credentials",
    "Access-Token-URL": "",
    accessTokenExpiry: ""
  }
});

export default function() {
  postman[Request]({
    name: "Collection Mock",
    id: "",
    method: "GET",
    address:
      "",
    headers: {
      Authorization: "Bearer {{currentAccessToken}}"
    },
    pre() {
      const echoPostRequest = {
        url: pm.environment.get("Access-Token-URL"),
        method: "POST",
        header: "Content-Type:x-www-form-urlencoded",
        body: {
          mode: "urlencoded",
          urlencoded: [
            { key: "client_id", value: pm.environment.get("Client-Id") },
            {
              key: "client_secret",
              value: pm.environment.get("Client-Secret")
            },
            { key: "grant_type", value: pm.environment.get("Grant-Type") },
            { key: "scope", value: pm.environment.get("Token-Scope") }
          ]
        }
      };

      var getToken = true;

      if (
        !pm.environment.get("accessTokenExpiry") ||
        !pm.environment.get("currentAccessToken")
      ) {
        console.log("Token or expiry date are missing");
      } else if (
        pm.environment.get("accessTokenExpiry") <= new Date().getTime()
      ) {
        console.log("Token is expired");
      } else {
        getToken = false;
        console.log("Token and expiry date are all good");
      }

      if (getToken === true) {
        pm.sendRequest(echoPostRequest, function(err, res) {
          console.log(err ? err : res.json());
          if (err === null) {
            console.log("Saving the token and expiry date");
            var responseJson = res.json();
            pm.environment.set("currentAccessToken", responseJson.access_token);

            var expiryDate = new Date();
            expiryDate.setSeconds(
              expiryDate.getSeconds() + responseJson.expires_in
            );
            pm.environment.set("accessTokenExpiry", expiryDate.getTime());
          }
        });
      }
    }
  });
}

问题出在pm.sendRequest上,转换器不支持,我不确定替代方法是什么。因此,我正在寻找从授权服务器动态请求访问令牌并使用该令牌向API发出请求以进行k6脚本中的负载测试的方法。

2 个答案:

答案 0 :(得分:0)

您已经看到sendRequest不被支持...

这主要是因为pm.sendRequest是异步的,但是k6 at this point doesn't have a event loop是这样的……因此,没有异步http调用:((http.batch除外,但是... 我发现您不太可能希望它是异步的……或者您目前无法用k6做到这一点……您可以重写它以使用k6's http.post

据我所见,应该看起来像

pre() {

      var getToken = true;

      if (
        !pm.environment.get("accessTokenExpiry") ||
        !pm.environment.get("currentAccessToken")
      ) {
        console.log("Token or expiry date are missing");
      } else if (
        pm.environment.get("accessTokenExpiry") <= new Date().getTime()
      ) {
        console.log("Token is expired");
      } else {
        getToken = false;
        console.log("Token and expiry date are all good");
      }

      if (getToken === true) {
          let res = http.post(pm.environment.get("Access-Token-URL"), {
           "client_id": pm.environment.get("Client-Id") ,
           "client_secret": pm.environment.get("Client-Secret"),
           "grant_type": pm.environment.get("Grant-Type"),
           "scope": pm.environment.get("Token-Scope")
          });
          console.log(err ? err : res.json());
          if (err === null) {
            console.log("Saving the token and expiry date");
            var responseJson = res.json();
            pm.environment.set("currentAccessToken", responseJson.access_token);

            var expiryDate = new Date();
            expiryDate.setSeconds(
              expiryDate.getSeconds() + responseJson.expires_in
            );
            pm.environment.set("accessTokenExpiry", expiryDate.getTime());
          }
    }

免责声明:我从未使用过邮递员,并且上面的代码是手工编写/复制粘贴的,未经测试:)

答案 1 :(得分:0)

我最终使用以下代码段成功拨打了电话:

// Auto-generated by the Load Impact converter

import "./libs/shim/core.js";
import http from "k6/http";
import { check, sleep } from "k6";

export let options = {
  max_vus: 10,
  vus: 10,
  stages: [
    { duration: "1m", target: 10 }
  ]
}

const Request = Symbol.for("request");

pm.environment.set("currentAccessToken", "");
pm.environment.set("accessTokenExpiry", "");
pm.environment.set("clientId", "");
pm.environment.set("clientSecret", "");
pm.environment.set("tokenScope", "");
pm.environment.set("grantType", "");
pm.environment.set("accesstokenUrl", "");

pm.environment.set("apiUrl", "");

pm.environment.set("subscriptionKeys", "");

export default function() {     
    var getToken = true;

    if (!pm.environment.get("accessTokenExpiry") || !pm.environment.get("currentAccessToken")) {
        //console.log("Token or expiry date are missing");
    } else if (pm.environment.get("accessTokenExpiry") <= new Date().getTime()) {
        //console.log("Token is expired");
    } else {
        getToken = false;
        //console.log("Token and expiry date are all good");
    }

    if (getToken === true) {
        //get the access token first
        let res = http.post(pm.environment.get("accesstokenUrl"), {
        "client_id": pm.environment.get("clientId"),
        "client_secret": pm.environment.get("clientSecret"),
        "grant_type": pm.environment.get("grantType"),
        "scope": pm.environment.get("tokenScope")
        });

        var checkRes = check(res, {
            "Token Request status is 200": (r) => r.status === 200,
        });

        if (checkRes) {
            var responseJson = res.json();
            pm.environment.set("currentAccessToken", responseJson.access_token);
            var expiryDate = new Date();
            expiryDate.setSeconds(
              expiryDate.getSeconds() + responseJson.expires_in
            );
            pm.environment.set("accessTokenExpiry", expiryDate.getTime());
        }

        sleep(1);

        //make the api request using the access token and subscription keys (if required)
        let apiRes = http.get(pm.environment.get("apiUrl"),
        { 
            headers: { "Authorization": "Bearer " + pm.environment.get("currentAccessToken"), 
                       "Subscription-Key" : pm.environment.get("subscriptionKeys") 
            } 
        });
        check(apiRes, {
            "API Request status is 200": (res) => res.status === 200
        });

        sleep(3);
    }
}