C# 如何为使用包装器的Azure函数编写单元测试?
我在所有Azure函数上使用包装器类:C# 如何为使用包装器的Azure函数编写单元测试?,c#,unit-testing,.net-core,dependency-injection,azure-functions,C#,Unit Testing,.net Core,Dependency Injection,Azure Functions,我在所有Azure函数上使用包装器类: public interface IFunctionWrapper { Task<IActionResult> Execute(HttpRequest req, ExecutionContext context, Func<Task<IActionResult>> azureFunction); } public class FunctionWrapper : IFunctionWrapper { pr
public interface IFunctionWrapper
{
Task<IActionResult> Execute(HttpRequest req, ExecutionContext context, Func<Task<IActionResult>> azureFunction);
}
public class FunctionWrapper : IFunctionWrapper
{
private readonly ILogger _log;
public FunctionWrapper(ILogger<FunctionWrapper> log)
{
_log = log;
}
public async Task<IActionResult> Execute(HttpRequest req, ExecutionContext context, Func<Task<IActionResult>> azureFunction)
{
try
{
// Log few extra information to Application Insights
// Do authentication
return await azureFunction();
}
catch (Exception ex)
{
// Return a custom error response
}
}
}
公共接口IFunctionWrapper
{
任务执行(HttpRequest请求、ExecutionContext上下文、Func azureFunction);
}
公共类FunctionWrapper:IFFunctionWrapper
{
私有只读ILogger_日志;
公共函数包装器(ILogger日志)
{
_log=log;
}
公共异步任务执行(HttpRequest请求、ExecutionContext上下文、Func azureFunction)
{
尝试
{
//在Application Insights中记录一些额外信息
//进行身份验证
返回等待azureFunction();
}
捕获(例外情况除外)
{
//返回自定义错误响应
}
}
}
下面是它在函数中的用法:
public class MyFunctions
{
private readonly IFunctionWrapper _functionWrapper;
public MyFunctions(IFunctionWrapper functionWrapper)
{
_functionWrapper = functionWrapper;
}
public async Task<IActionResult> GetPost(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)] HttpRequest req,
ExecutionContext context,
ILogger log)
{
return await _functionWrapper.Execute(req, context, async () =>
{
// Function code...
return new JsonResult(post);
});
}
}
公共类MyFunctions
{
私有只读IFunctionWrapper\u functionWrapper;
公共MyFunctions(IFunctionWrapper函数包装器)
{
_functionWrapper=functionWrapper;
}
公共异步任务GetPost(
[HttpTrigger(AuthorizationLevel.Anonymous,“get”,Route=null)]HttpRequest请求,
ExecutionContext上下文,
ILogger日志)
{
return wait\u functionWrapper.Execute(req,context,async()=>
{
//函数代码。。。
返回新的JsonResult(post);
});
}
}
我正在尝试为这个GetPost函数编写单元测试。在这种情况下,如何模拟FunctionWrapper类?模拟包装抽象所需的行为 下面的示例使用MOQ模拟包装器。注意模拟的设置
[TestClass]
public class MyFunctionsTests {
[TestMethod]
public async Task GetPost_Should_Execute_Wrapper() {
//Arrange
//mock the wrapper
IFunctionWrapper wrapper = Mock.Of<IFunctionWrapper>();
//configure the mocked wrapper to behave as expected when invoked
Mock.Get(wrapper)
.Setup(_ => _.Execute(It.IsAny<HttpRequest>(), It.IsAny<ExecutionContext>(), It.IsAny<Func<Task<IActionResult>>>()))
.Returns((HttpRequest r, ExecutionContext c, Func<Task<IActionResult>> azureFunction) =>
azureFunction()); //<-- invokes the delegate and returns its result
MyFunctions function = new MyFunctions(wrapper);
//these should be initialized as needed for the test
HttpRequest req = null;
ExecutionContext ctx = null;
ILogger log = Mock.Of<ILogger>();
//Act
IActionResult result = await function.GetPost(req, ctx, log);
//Assert
result.Should().NotBeNull();
//verify that mocked wrapper was called
Mock.Get(wrapper).Verify(_ => _.Execute(It.IsAny<HttpRequest>(), It.IsAny<ExecutionContext>(), It.IsAny<Func<Task<IActionResult>>>()));
//...perform other assertions here
}
}
[TestClass]
公共类MyFunctionsTests{
[测试方法]
公共异步任务GetPost_应_执行_包装器(){
//安排
//嘲笑包装纸
IFunctionWrapper=Mock.Of();
//将模拟包装器配置为在调用时按预期运行
Mock.Get(包装器)
.Setup(=>u.Execute(It.IsAny(),It.IsAny(),It.IsAny()))
.Returns((HttpRequest r、ExecutionContext c、Func azureFunction)=>
azureFunction();///执行(It.IsAny(),It.IsAny(),It.IsAny());
//…在此执行其他断言
}
}
原始问题中的代码省略了测试对象的大部分主体。这就是说,本示例基于最初提供的内容,用于创建用于创建上述测试的可复制示例您根本不需要创建包装器接口:
是可模拟的:HttpRequest
可以被模拟(或者只是一个POCO)ExecutionContext
可以模拟ILogger
- 使用依赖项注入来注入函数的依赖项(然后模拟这些依赖项)
- 请记住,您确实只想测试参数验证和可能的解析是否正常工作