简体   繁体   English

如何对时间触发的 azure function 进行单元测试? 我的测试不起作用

[英]How to unit test azure function triggered by time? My test doesn't work

At first, code from my test:首先,我的测试代码:

using Microsoft.AspNetCore.Http;
using Moq;
using NUnit.Framework;
using System.IO;
using System.Threading.Tasks;
using TeamsAllocationManager.Api.Functions;
using TeamsAllocationManager.Contracts.Base;
using TeamsAllocationManager.Contracts.EmployeeWorkingTypeHistory;
using Microsoft.Extensions.Logging;
using System.Linq.Expressions;
using System;

namespace TeamsAllocationManager.Tests.Functions
{
    [TestFixture]
    public class HistoryClearingFunctionTests
    {
        private readonly ILogger _mockedLogger;
        private readonly Mock<IDispatcher> _dispatcherMock;

        public HistoryClearingFunctionTests()
        {
            _mockedLogger = new Mock<ILogger>().Object;
            _dispatcherMock = new Mock<IDispatcher>();
        }

        [Test]
        public async Task ShouldCallClearOldEmployeeWorkingTypeHistoryRecordsCommand() =>
            await VerifyFunctionExecutionAsync(c => c.DispatchAsync<ClearOldEmployeeWorkingTypeHistoryRecordsCommand, bool>(It.IsAny<ClearOldEmployeeWorkingTypeHistoryRecordsCommand>(), default), "GET");
        private async Task VerifyFunctionExecutionAsync(Expression<Action<IDispatcher>> expression, string verb, string path = "", QueryCollection? query = null, MemoryStream? body = null)
        {
            // given
            var function = new HistoryClearingFunction(_dispatcherMock.Object);
            var reqMock = new Mock<HttpRequest>();
            reqMock.Setup(r => r.Method).Returns(verb);
            reqMock.Setup(r => r.Query).Returns(query ?? new QueryCollection());
            reqMock.Setup(r => r.Body).Returns(body ?? new MemoryStream());

            // when
            await function.RunAsync(reqMock.Object, path, _mockedLogger);

            // then
            _dispatcherMock.Verify(expression, Times.Once);
        }
    }
}

Currently i have one error at line 29, where i have await VerifyFunctionExecutionAsync.目前我在第 29 行有一个错误,我在那里等待 VerifyFunctionExecutionAsync。 The error was on DispatchAsync<Clear***Command> and it sounds like this:错误出现在 DispatchAsync<Clear***Command> 上,听起来像这样:

'TeamsAllocationManager.Contracts.EmployeeWorkingTypeHistory.ClearOldEmployeeWorkingTypeHistoryRecordsCommand' cannot be used as type parameter 'TCommand' in the generic type or method 'ICommandDispatcher.DispatchAsync(TCommand, CancellationToken)'. “TeamsAllocationManager.Contracts.EmployeeWorkingTypeHistory.ClearOldEmployeeWorkingTypeHistoryRecordsCommand”不能用作泛型类型或方法“ICommandDispatcher.DispatchAsync(TCommand, CancellationToken)”中的类型参数“TCommand”。 There is no implicit reference conversion from 'TeamsAllocationManager.Contracts.EmployeeWorkingTypeHistory.ClearOldEmployeeWorkingTypeHistoryRecordsCommand' to 'TeamsAllocationManager.Contracts.Base.Commands.ICommand'.没有从“TeamsAllocationManager.Contracts.EmployeeWorkingTypeHistory.ClearOldEmployeeWorkingTypeHistoryRecordsCommand”到“TeamsAllocationManager.Contracts.Base.Commands.ICommand”的隐式引用转换。 TeamsAllocationManager.Tests TeamsAllocationManager.Tests

Im newbie in azure functions and don't know how to fix it.我是 azure 功能的新手,不知道如何修复它。 The rest of code (tested function) works fine, so there is only issue with test. rest 的代码(测试功能)工作正常,所以只有测试有问题。

#Update 1 Fixed bugs in code above and add the function code below: #Update 1 修复了上面代码中的错误,并在下面添加了 function 代码:

using Microsoft.Azure.WebJobs;
using System.Threading.Tasks;
using TeamsAllocationManager.Contracts.Base;
using TeamsAllocationManager.Contracts.EmployeeDeskHistory;
using TeamsAllocationManager.Contracts.EmployeeWorkingTypeHistory;

namespace TeamsAllocationManager.Api.Functions
{
    public class HistoryClearingFunction : FunctionBase
    {
        private readonly IDispatcher _dispatcher;
        public HistoryClearingFunction(IDispatcher dispatcher)
        {
            _dispatcher = dispatcher;
        }
        [FunctionName("EmployeeWorkingTypeHistoryClearingFunction")]
        public async Task EmployeeWorkingTypeHistoryClearingFunction([TimerTrigger("0 0 0 1 * *")]TimerInfo myTimer) 
        {
            await _dispatcher.DispatchAsync<ClearOldEmployeeWorkingTypeHistoryRecordsCommand, bool>(new ClearOldEmployeeWorkingTypeHistoryRecordsCommand());
        }
        [FunctionName("EmployeeDeskHistoryClearingFunction")]
        public async Task EmployeeDeskHistoryClearingFunction([TimerTrigger("0 0 0 1 * *")] TimerInfo myTimer)
        {
            await _dispatcher.DispatchAsync<ClearOldEmployeeDeskHistoryRecordsCommand, bool>(new ClearOldEmployeeDeskHistoryRecordsCommand());
        }
    }
}

Current error:当前错误:

Message: Moq.MockException: Expected invocation on the mock once, but was 0 times: c => c.DispatchAsync<ClearOldEmployeeWorkingTypeHistoryRecordsCommand, bool>(It.IsAny(), CancellationToken)消息:Moq.MockException:预期在模拟上调用一次,但为 0 次:c => c.DispatchAsync<ClearOldEmployeeWorkingTypeHistoryRecordsCommand, CancellationToken>(It.IsAny()

Performed invocations:执行的调用:

MockIDispatcher:1 (c): MockIDispatcher:1 (c):

No invocations performed.未执行任何调用。

I would recommend to solve this by a architectural change.我建议通过架构更改来解决这个问题。

Move all functional code that is not direct related to the function Technologie itself into a helper class.将所有与 function 技术本身不直接相关的功能代码移动到帮助程序 class 中。 Then write the UnitTest against this helper class.然后针对这个助手 class 编写 UnitTest。

This will make it much easier to test the code that is doing the productive work.这将使测试执行生产性工作的代码变得更加容易。

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

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