簡體   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