c# - 如何模拟从 Azure Function 调用的方法?
问题描述
Azure Functions 的问题是它们的 Run 函数必须是静态的。此 Run 函数调用一个执行数据库搜索查询的函数。我很想模拟这个功能
namespace Something.App{
public class Something {
[FunctionName("Something")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequest req,
ILogger log)
{
//perform something
dbCall(); // I wish to mock
//perform something
return new OkObjectResult(result);
}
然而,对此的嘲笑尝试失败了。测试本身运行,但它不运行模拟版本,它只是运行使用互联网连接的原始版本。
namespace Something.Test{
public class SomethingTest{
private readonly ILogger logger = TestFactory.CreateLogger();
private Mock<Something> CreateMockObject(){
var mock = new Mock<Something>();
mock.SetupSequence(f => f.dbCall()).Returns(something);
return mock;
}
[Fact]
public async void Http_Respond_On_Valid_Data()
{
CreateMockObject();
Dictionary<string,StringValues> postParam= new Dictionary<string,StringValues>();
postParam.Add("param", "value");
var request = new DefaultHttpRequest(new DefaultHttpContext()){
Query = new QueryCollection(postParam)
};
var response = (OkObjectResult)await Something.Run(request, logger);
string stringResponse = (String) response.Value;
Assert.Equal("XKCD", stringResponse);
}
我试图将该方法分成一个非静态类(比如说SomethingTool)并实现这样的目标。
namespace Something.App{
public class Something {
[FunctionName("Something")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequest req,
ILogger log)
{
SomethingTool object = new SomethingTool();
//perform something
object.dbCall(); // I wish to mock
//perform something
return new OkObjectResult(result);
}
但它并没有完成这项工作。对于这个项目,使用 Moq 是必须的。
解决方案
最简单的方法是重构函数以抽象出依赖关系,以便在测试时可以根据需要替换它们
例如
public static class Something {
public static Func<ISomeDependency> Factory = () => return new SomeDependency();
[FunctionName("Something")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequest req,
ILogger log) {
//...
ISomeDependency tool = Factory.Invoke();
var result = await tool.dbCall();
//...
return new OkObjectResult(result);
}
}
现在可以像这样测试
public class SomethingTest{
private readonly ILogger logger = TestFactory.CreateLogger();
[Fact]
public async Task Http_Respond_On_Valid_Data() {
//Arrange
var expected = "XKCD";
var mock = new Mock<ISomeDependency>();
mock.Setup(_ => _.dbCall()).ReturnsAsync(expected);
Something.Factory = () => return mock.Object; //<-- replace factory delegate
var postParam = new Dictionary<string, StringValues>();
postParam.Add("param", "value");
var request = new DefaultHttpRequest(new DefaultHttpContext()){
Query = new QueryCollection(postParam)
};
//Act
var response = (OkObjectResult)await Something.Run(request, logger);
string actual = (String) response.Value;
//Assert
Assert.Equal(expected, actual);
}
}
实际实现将在调用时使用该函数,但在单独对函数进行单元测试时可以替换为工厂方法。
推荐阅读
- javascript - 有没有办法显示不和谐机器人正在服务的成员
- c# - 循环遍历 C# 中的网格按钮以计算黑色方块
- vue.js - 用 jest 进行 Vue 测试:$route 始终未定义
- vue.js - Router.beforeEach 跳转回登录页面,登录后重置vuex状态值
- java - 如何在spring boot中将对象从jsp传递到控制器
- javascript - Javascript - 数组的第一个元素返回未定义
- .net - .Net 核心和基于角色的授权
- ios - iOS corebluetooh 在后台做广告
- logging - 如何格式化 Azure DevOps 控制台日志
- rust - 如何在 Rust 中将 impl<'a> From<&'a Method> 用于 &'a str?