如何在仓储模式下Mock带筛选参数的Microsoft Graph API并做单元测试
仓储模式下Mock Microsoft Graph API的单元测试方案
你的问题核心是当前Mock设置忽略了传入的筛选参数,导致无论传什么值都返回全部用户,无法验证仓储层的筛选调用逻辑。以下是正确的Mock和单元测试实现方式:
1. 准备测试数据
先定义一组测试用的用户数据,覆盖不同筛选场景:
// 假设TMUser是你的业务用户模型,User是Graph API的用户模型 private readonly List<TMUser> _testUsers = new List<TMUser> { new TMUser { Id = "1", DisplayName = "TestUser-1", GivenName = "John", Mail = "john@test.com" }, new TMUser { Id = "2", DisplayName = "AnotherUser", GivenName = "Jane", Mail = "jane@test.com" }, new TMUser { Id = "3", DisplayName = "TestUser-2", GivenName = "Test", Mail = "test@test.com" } };
2. 正确配置Mock逻辑
不要用It.IsAny<string>()固定返回全部数据,而是通过回调函数根据传入的参数动态模拟Graph API的筛选行为:
private readonly Mock<IGraphAPI> _graphApiMock = new Mock<IGraphAPI>(); // 在测试初始化方法([TestInitialize])中配置Mock [TestInitialize] public void Setup() { // 将业务用户模型转换为Graph API的User模型集合 var graphUsers = _testUsers.Select(u => new User { Id = u.Id, DisplayName = u.DisplayName, GivenName = u.GivenName, Surname = u.Surname, Mail = u.Mail, OtherMails = u.OtherMails, CompanyName = u.CompanyName }).ToList(); // 配置Mock:根据传入的param参数筛选并返回结果 _graphApiMock.Setup(api => api.GetUserByNameAsync(It.IsAny<string>())) .ReturnsAsync((string param) => { // 模拟Graph API的筛选逻辑(和真实API逻辑一致) var filteredUsers = graphUsers.Where(u => u.DisplayName.StartsWith(param, StringComparison.OrdinalIgnoreCase) || u.GivenName.StartsWith(param, StringComparison.OrdinalIgnoreCase) || u.Surname.StartsWith(param, StringComparison.OrdinalIgnoreCase) || u.Mail.StartsWith(param, StringComparison.OrdinalIgnoreCase) ).ToList(); // 包装成Graph API返回的集合页类型 return new GraphServiceUsersCollectionPage(filteredUsers, null); }); // 初始化仓储实例,注入Mock的IGraphAPI this.b2CRepository = new B2CRepository(_graphApiMock.Object); }
3. 编写单元测试用例
测试用例需要验证三个核心点:返回结果符合预期、参数正确传递给Graph API、方法调用次数正确:
[TestMethod] public async Task GetUsersByName_WithValidParam_ReturnsFilteredUsers() { // Arrange var searchParam = "TestUser-"; var expectedUserCount = 2; // Act var result = await this.b2CRepository.GetUsersByName(searchParam); // 建议把仓储方法改成异步,避免.Result死锁 // Assert // 验证返回数量正确 Assert.AreEqual(expectedUserCount, result.Count); // 验证所有返回用户都匹配筛选条件 Assert.IsTrue(result.All(u => u.DisplayName.StartsWith(searchParam))); // 验证Graph API方法被调用一次,且参数正确 _graphApiMock.Verify(api => api.GetUserByNameAsync(searchParam), Times.Once); } [TestMethod] public async Task GetUsersByName_WithNoMatchingParam_ReturnsEmptyList() { // Arrange var searchParam = "NonExistentUser"; // Act var result = await this.b2CRepository.GetUsersByName(searchParam); // Assert Assert.AreEqual(0, result.Count); _graphApiMock.Verify(api => api.GetUserByNameAsync(searchParam), Times.Once); }
关键注意事项
- 仓储层的
GetUsersByName方法建议改为异步(返回Task<List<TMUser>>),避免使用.Result导致的死锁风险。 - 单元测试只关注仓储层的逻辑:是否正确传递参数、是否正确转换Graph API的返回结果,不要测试Graph API本身的筛选逻辑(那是集成测试的范畴)。
- 使用
Verify方法验证依赖的IGraphAPI接口是否被正确调用,确保仓储层的逻辑符合预期。
内容的提问来源于stack exchange,提问作者Tim Whatley
相关产品推荐
相关产品推荐

