簡體   English   中英

對時間觸發的 Azure 函數進行單元測試

[英]Unit Test a Time Triggered Azure Function

我有一個時間觸發的 Azure 函數,我想用 XUnit 和 MOQ 測試它。

雖然我知道我需要使用類的實例調用該類的Run方法,但說funTimeTriggeredObj where

funTimeTriggered funTimeTriggeredObj = new funTimeTriggered(queueSchedulerMock.Object, telemetryHelperMock.Object)

funTimeTriggeredObj.Run(param1, param2, loggerMock.Object) 

在哪里

private Mock<ILogger> loggerMock = new Mock<ILogger>() 

我不確定我應該如何模擬分別是TimerInfoExecutionContext對象的param1param2

我問的原因是因為“TimerInfo”和“ExecutionContext”都沒有實現任何可以模擬的接口。

下面是我的實際功能實現。 任何幫助將不勝感激。

using System;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Extensions.Logging;

public  class funTimeTriggered
{
    private  string  _invocationID;
    private readonly IQueueScheduler _queueScheduler;
    private readonly ITelemetryHelper _telemetryHelper;

    public funTimeTriggered(IQueueScheduler queueScheduler, ITelemetryHelper telemetryHelper)
    {
        _queueScheduler = queueScheduler;
        _telemetryHelper = telemetryHelper;
    }

    [FunctionName("funTimeTriggered")]
    public  async Task Run([TimerTrigger("0/10 * * * * *")]TimerInfo myTimer, ExecutionContext context, ILogger log)
    {
        log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
        try
        {
            _invocationID = context.InvocationId.ToString();
            await _queueScheduler.SendEventsToServiceBusAndDeleteFromSQS();
        }
        catch (Exception ex)
        {
            log.LogError(ex.Message);
            _telemetryHelper.LogException(ex);
            throw ex;
        }
    }
}

如果使用這些類的實際實例沒有不良影響,並且您可以實際初始化它們,然后創建實際實例並將它們傳遞給被測函數。

如果使用實際實例沒有不良影響,則它們不必是接口或模擬

//Arrange

//...omitted for brevity

var param1 = new TimerInfo(...); 
var param2 = = new ExecutionContext {
    InvocationId = Guid.NewGuid()
};

//Act
await funTimeTriggeredObj.Run(param1, param2, loggerMock.Object);

//Assert
//...assert expected behavior

由於在這個測試用例中定時器甚至沒有被函數使用,所以可以完全忽略它

//Arrange

//...omitted for brevity

var param1 = default(TimerInfo); //null
var param2 = = new ExecutionContext {
    InvocationId = Guid.NewGuid()
};

//Act
await funTimeTriggeredObj.Run(param1, param2, loggerMock.Object);

//Assert
//...assert expected behavior

您可以將 Azure 函數的邏輯放在一個單獨的類中,並為該類編寫單元測試。

可以做的是集成測試,如果使用不同的觸發器(例如 HTTP)創建了另一個函數,做同樣的事情。

設置是對的。 但是,與其嘗試模擬 TimerInfo 和 ExecutionContext 或實現它們,不如簡單地發送 null,因為您不在函數中使用它們。

我有我需要做的類似測試。 雖然我使用了 FakeItEasy,但我希望這會幫助你(或其他人)。

使用的軟件包:

<PackageReference Include="FakeItEasy" Version="6.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
<PackageReference Include="xunit" Version="2.4.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
<PackageReference Include="coverlet.collector" Version="1.2.0" />

一些測試:

public class FunTimeTriggeredConstructorTests
{
    private ITelemetryHelper _fakeITelemetryHelper;
    private IQueueScheduler _fakeIQueueScheduler;

    public FunTimeTriggeredConstructorTests()
    {
        _fakeITelemetryHelper= A.Fake<ITelemetryHelper >();
        _fakeIQueueScheduler = A.Fake<IQueueScheduler>();
    }

    [Fact]
    public void ShouldThrow_ArgumentNullException_When_IQueueScheduler_Is_Null()
    {
        _fakeIQueueScheduler = null;

        Assert.Throws<ArgumentNullException>(() => new FunTimeTriggered(_fakeITelemetryHelper, _fakeIQueueScheduler));
    }
}

public class RunTests
{
    private ITelemetryHelper _fakeITelemetryHelper;
    private IQueueScheduler _fakeIQueueScheduler;
    private TimerInfo _fakeTimerInfo;
    private ExecutionContext _fakeExecutionContext;
    private ILogger _fakeILogger;
    private FunTimeTriggered _funTimeTriggered;

    public RunTests()
    {
        _fakeITelemetryHelper= A.Fake<ITelemetryHelper>();
        _fakeTimerInfo = A.Fake<TimerInfo>();
        _fakeIQueueScheduler = A.Fake<IQueueScheduler>();
        _fakeExecutionContext = A.Fake<ExecutionContext>();
        _fakeILogger = A.Fake<ILogger>();

        _funTimeTriggered = new FunTimeTriggered(_fakeITelemetryHelper, _fakeIQueueScheduler);
    }

    [Fact]
    public async Task ShouldCall_IQueueScheduler_SendEventsToServiceBusAndDeleteFromSQS_AtMost_Once()
    {
        A.CallTo(() => _fakeExecutionContext.InvocationId).Returns("");

        await FunTimeTriggered.Run(_fakeTimerInfo, _fakeExecutionContext, _fakeILogger);

        A.CallTo(() => _queueScheduler.SendEventsToServiceBusAndDeleteFromSQS()).MustHaveHappenedOnceExactly();
    }
}
 // Arrange
 TimerSchedule schedule = new DailySchedule("2:00:00");
 TimerInfo timerInfo = new TimerInfo(schedule, It.IsAny<ScheduleStatus>(), false);
    
 // Act
 await _functions.TimerTrigerFunction(timerInfo, _durableOrchestrationClient.Object, _log.Object);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM