Function App单元测试:GetInput与数据仓储返回失效问题排查
问题分析与解决
核心问题
业务代码硬编码实例化仓储,未提供依赖注入入口,导致单元测试中的Mock仓储无法替换真实仓储,Mock配置完全不生效。同时测试代码还存在接口不匹配、拼写错误等问题。
业务代码问题点
- 静态方法
Repository()直接new RepoData(),无依赖注入设计,单元测试无法拦截实例化过程。 - 变量引用错误:
Guid.Parse(entitydataobject.Guid)应为Guid.Parse(eventDetails.Guid),否则编译报错。 Processor方法无返回值,测试中的Assert.IsTrue(result.Result)会因默认返回false失败。
测试代码问题点
- Mock接口不匹配:业务代码依赖
IRepoData,但测试Mock的是IRepository;方法名也不匹配,业务用GetEntityList,测试Setup的是GetEntityIdList。 - Mock仓储未注入:测试代码未将Mock实例传入业务逻辑,业务仍调用真实仓储构造。
- 拼写错误:
Mock<IDurableOrchestrationContest>应为Mock<IDurableOrchestrationContext>;mockContext.Setup返回的entitydataobject应为inputData。 - 缺少测试特性:测试方法未加
[TestMethod],无法被测试框架识别。
修复步骤
1. 重构业务代码,支持依赖注入
修改Processor方法,添加仓储参数用于注入,兼容原有生产逻辑:
namespace program { [FunctionName("Processor")] // 添加IRepoData参数,支持依赖注入 public static async Task<bool> Processor([OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log, IRepoData repo = null) { var eventDetails = context.GetInput<entitydataobject>(); List<Guid> list; try { // 优先使用注入的仓储,无注入则创建默认实例 repo = repo ?? Repository(); // 修正变量引用错误 list = repo.GetEntityList(Guid.Parse(eventDetails.Guid), eventDetails.Name); // 根据业务逻辑补充返回值,示例返回true return true; } catch(Exception ex) { log.LogError("Processor Error: " + ex.Message); // 异常场景返回false return false; } } public static IRepoData Repository() { try { return new RepoData("Data Source=instance.local;Initial Catalog=database;integrated security=True;MultipleActiveResultSets=True;"); } catch (Exception ex) { throw new Exception("Repository Error: " + ex.Message); } } }
2. 修正单元测试代码,注入Mock仓储
namespace Test { [TestClass] [ExcludeFromCodeCoverage] public class ProcessorTests { [TestMethod] public async Task Processor_ValidInput_ReturnsTrue() { // 修正拼写错误 var mockContext = new Mock<IDurableOrchestrationContext>(); var inputData = JsonConvert.DeserializeObject<entitydataobject>(File.ReadAllText("file.json")); var list = new List<Guid> { new Guid(), new Guid() }; // 修正Mock接口为IRepoData var mockRepo = new Mock<IRepoData>(); var log = new Mock<ILogger>(); // 匹配业务代码的方法名和参数 mockRepo.Setup(repo => repo.GetEntityList( Guid.Parse(inputData.Guid), inputData.Name )).Returns(list); // 修正返回变量 mockContext.Setup(x => x.GetInput<entitydataobject>()).Returns(inputData); // 将Mock仓储传入Processor方法 var result = await program.Processor(mockContext.Object, log.Object, mockRepo.Object); Assert.IsTrue(result); } } }
3. 关键说明
- 通过可选参数实现依赖注入,既兼容生产环境原有逻辑,又给单元测试提供Mock入口。
- 统一接口、方法名和变量引用,确保测试与业务逻辑匹配。
- 添加
[TestMethod]特性,让测试框架识别并执行测试。
内容的提问来源于stack exchange,提问作者HumblePirate
相关产品推荐
相关产品推荐

