繁体   English   中英

azure function 重试场景的单元测试用例 - nodejs

[英]azure function unit test cases for retry scenario - nodejs

我已经使用 NodeJs 构建了一个 azure function。 我正在使用 Jest 进行测试。

场景: function拨打API,如果3rd返回Timeout,我需要重试1次后退出。 当实时并且服务器按预期自动重试时,这工作正常。

我未能编写测试用例,因为出现 Jest Timeout 错误。

逻辑:

function.json

"retry": {
    "strategy": "exponentialBackoff",
    "maxRetryCount": 1,
    "minimumInterval": "00:00:10",
    "maximumInterval": "00:00:40"
}

index.js - 在 try/catch 下

catch (err) {
                let errorCode = err.errorCode || err.code || 500;                   
                let errorMessage = err.message|| err.errorMessage;
                if (errorMessage && errorMessage.indexOf("ETIMEDOUT") >= 0 ) {
                    errorCode = 429; //setting errorCode as 429 to retry automatically from azure function
                    let retryError = new Error("retrying requests");
                    retryError.code = 429;
                    throw retryError;
                }else{
                   context.done();
                }
           };

索引.test.js

测试套件无法运行重试请求

一旦从主 class 抛出错误,测试 class 将在“ let retryError = new Error("retrying requests"); ”这一行中断。

那么,如果服务器重试耗尽,仍然响应429,如何编写测试用例?

我正在按照这个文档在 Nodejs Azure function 中实现自动化测试。 步骤如下:

要在 VS 代码扩展中测试 Azure function,请使用 Jest。

使用npm i jest

更新package.json以用以下命令替换现有的测试命令

"scripts": {
    "test": "jest"
}

对于自动化测试,您可以创建一个模块来运行测试。 创建一个您喜欢的新文件夹 ( testing ) 在创建的文件夹中添加一个新文件 ( defaultContext.js ) 并添加以下命令以记录 function 默认执行上下文。

module.exports = {
    log: jest.fn()
};

在此处输入图像描述

之后在 HTTP function 触发器文件夹中添加一个新文件index.test.js并添加以下代码

const httpFunction = require('./index');
const context = require('../testing/defaultContext')
test('Http trigger should return known text', async () => {
    const request = {
    query: { name: 'Bill' }
};
await httpFunction(context, request);
expect(context.log.mock.calls.length).toBe(1);
expect(context.res.body).toEqual('Hello Bill');
});

使用npm test命令运行单元测试。

尝试在 azure function 中添加重试策略

在您的触发器中添加重试策略function.json使用固定延迟指数退避

{
    "disabled": false,
    "bindings": [
    {
        ....
    }
    ],
    "retry": {
        "strategy": "exponentialBackoff",
        "maxRetryCount": 5,
        "minimumInterval": "00:00:10",
        "maximumInterval": "00:15:00"
    }
}

在此处输入图像描述

使用npm test添加所有运行测试后,我可以看到结果:

在此处输入图像描述

重试限制:

在消费计划中,

在重试队列中的最终消息时,应用程序可能会缩小到 &

执行重试时,应用程序可能会缩小。 选择重试间隔<= 00:01:00<= 5次重试以获得更好的结果。

警告不建议将服务总线队列等触发器的传递计数设置为 1,这意味着消息将在单个 function 重试周期后立即被死信。 这是因为触发器通过重试提供弹性,而 function 重试策略是尽最大努力,可能会导致重试总数少于所需的总数。

参考这里

刚刚修改了结构以捕获每个错误,如下所示:

try {
                    await retry(
                        async(bail) => {
                            api_attempt++;
                            console.log('correlationId:' + correlationId + ' api_attempt:' + api_attempt);
                            let api_Resp = await myAPI(correlationId, payload)
                                .catch((error) => {
                                    console.error("correlationId:" + correlationId + " myAPI caught error::", JSON.stringify(error));
                                    let errorCode = error.statusCode;
                                    let errorMessage = error.errorMessage;
                                    let errorDescription = error.errorDescription;
                                    console.log("correlationId:" + correlationId + " myAPI errorCode::" + errorCode);
                                    if (errorCode === 429 ||
                                        (errorMessage && (errorMessage.indexOf("ETIMEDOUT") >= 0 || errorMessage.indexOf("ECONNREFUSED") >= 0 || errorMessage.indexOf("Timeout") >= 0)) ||
                                        (errorDescription && (errorDescription.indexOf("ETIMEDOUT") >= 0 || errorDescription.indexOf("ECONNREFUSED") >= 0 || errorDescription.indexOf("Timeout") >= 0 || errorDescription.indexOf("retries exhausted") >= 0))
                                    ) {
                                        console.log("correlationId:" + correlationId + " retrying myAPI");
                                        throw error; //to retry
                                    } else if (errorCode === 500) {
                                        console.log("correlationId:" + correlationId + " exiting myAPI and not writing to db");
                                        return; //don't bail and don't write to DB (as 3Party writes to DB for 500 status)
                                    } else {
                                        // don't retry by bailing error 
                                        console.log("correlationId:" + correlationId + " not attempting myAPI retry..");
                                        bail(error);
                                        return;
                                    }
                                })
                        }, retryOptions);
                } catch (err) {
                    console.error("correlationId:" + correlationId + " myAPI final error::api_attempt:" + api_attempt + " - retries exhausted while calling API::", JSON.stringify(err));
                    let errorCode = err.statusCode || 500;
                    let errorMessage = err.code || err.errorMessage || err.message || err;
                    let errorDescription = err.statusMessage || err.errorDescription || errorMessage || "Unknown Error at 3Party Single API";
                    //writing errors to db
                    callDB(false, correlationId, payload, 'AzureFunction', 'Request failed at 3Party', errorCode, errorMessage, errorDescription);
                }

暂无
暂无

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

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