Azure函数的问题在于它们的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);
}
但是,对此的模拟尝试失败。该测试本身已经运行,但是它没有运行模拟版本,只是运行了使用Internet连接的原始版本。
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。
答案 0 :(得分:2)
最简单的方法是重构功能以抽象出依赖项,以便在测试时可以根据需要替换它们
例如
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);
}
}
实际的实现将在调用时使用该函数,但是当单独对函数进行单元测试时,可以使用工厂方法代替。