我在所有Azure函数上使用包装器类:
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
}
}
}
这是函数中的用法:
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);
});
}
}
我正在尝试为此GetPost函数编写单元测试。在这种情况下如何模拟FunctionWrapper类?
答案 0 :(得分:2)
模拟包装抽象的所需行为。
以下示例使用最小起订量来模拟包装器。注意模拟的设置
[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
}
}
原始问题中的代码省略了测试对象的大部分身体。话虽如此,该示例基于最初提供的内容,用于创建可重复的示例,该示例用于创建上面的测试
答案 1 :(得分:0)
您根本不需要创建包装器接口:
HttpRequest
是可模拟的:https://mahmutcanga.com/2019/12/13/unit-testing-httprequest-in-c/ ExecutionContext
可以被模拟(或仅按原样使用POCO)ILogger
可以被模仿