简体   繁体   English

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

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

I have built an azure function using NodeJs.我已经使用 NodeJs 构建了一个 azure function。 And I am Using Jest for testing.我正在使用 Jest 进行测试。

Scenario: When making API calls from function, if the 3rd party returns Timeout, I need to retry 1 more time and then quit.场景: function拨打API,如果3rd返回Timeout,我需要重试1次后退出。 This is working fine when live and server is retrying automatically as expected.当实时并且服务器按预期自动重试时,这工作正常。

I am failing to write test cases as getting an Jest Timeout error.我未能编写测试用例,因为出现 Jest Timeout 错误。

Logic:逻辑:

function.json function.json

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

index.js - under try/catch 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();
                }
           };

index.test.js索引.test.js

Test suite failed to run retrying requests测试套件无法运行重试请求

The test class breaks at this line " let retryError = new Error("retrying requests"); " once the error is thrown from main class.一旦从主 class 抛出错误,测试 class 将在“ let retryError = new Error("retrying requests"); ”这一行中断。

So, if the server retry exhausted and still the response is 429, how to write test cases?那么,如果服务器重试耗尽,仍然响应429,如何编写测试用例?

I am following this Doc to implement automated test in Nodejs Azure function.我正在按照这个文档在 Nodejs Azure function 中实现自动化测试。 Steps follow:步骤如下:

To test the Azure function in VS code extension, use Jest.要在 VS 代码扩展中测试 Azure function,请使用 Jest。

Install jest using npm i jest使用npm i jest

Update the package.json to replace the existing test command with the below command更新package.json以用以下命令替换现有的测试命令

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

For automating tests you can create a module to run tests.对于自动化测试,您可以创建一个模块来运行测试。 Create a new folder which you prefer ( testing ) Add a new file ( defaultContext.js ) in a created folder and add the below command to log the function default execution context.创建一个您喜欢的新文件夹 ( testing ) 在创建的文件夹中添加一个新文件 ( defaultContext.js ) 并添加以下命令以记录 function 默认执行上下文。

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

在此处输入图像描述

After that add a new file index.test.js in the HTTP function trigger folder and add the below code之后在 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');
});

Use the npm test command to run the unit test.使用npm test命令运行单元测试。

Try adding retry policy in your azure function尝试在 azure function 中添加重试策略

Add retry policy in function.json in your trigger use fixedDelay or exponentialBackoff在您的触发器中添加重试策略function.json使用固定延迟指数退避

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

在此处输入图像描述

After adding all run the test using npm test I could see the results:使用npm test添加所有运行测试后,我可以看到结果:

在此处输入图像描述

Retry limitations:重试限制:

In the consumption plan,在消费计划中,

the app may be scaled down to zero while retrying the final messages in a queue.在重试队列中的最终消息时,应用程序可能会缩小到 & &

the app may be scaled down while performing retries.执行重试时,应用程序可能会缩小。 Choose a retry interval <= 00:01:00 and <= 5 retries for better result.选择重试间隔<= 00:01:00<= 5次重试以获得更好的结果。

Warning It is not recommended to set the delivery count for a trigger like Service Bus Queues to 1, meaning the message would be dead-lettered immediately after a single function retry cycle.警告不建议将服务总线队列等触发器的传递计数设置为 1,这意味着消息将在单个 function 重试周期后立即被死信。 This is because triggers provide resiliency with retries, while the function retry policy is best effort and may result in less than the desired total number of retries.这是因为触发器通过重试提供弹性,而 function 重试策略是尽最大努力,可能会导致重试总数少于所需的总数。

Refer here参考这里

Just modified the structure to catch every error as below:刚刚修改了结构以捕获每个错误,如下所示:

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