You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#使用Moq与xUnit单元测试时如何Mock GraphServiceClient调用

基于Moq Mock GraphServiceClient 调用的实现方案

前置重构要求

首先你需要调整原有业务代码的写法,不要直接在业务逻辑内实例化GraphServiceClient,改为通过依赖注入注入接口IGraphServiceClient,才可以完成Mock替换:

public class YourBusinessService
{
    private readonly IGraphServiceClient _graphClient;

    // 构造函数注入IGraphServiceClient,由DI容器完成初始化
    public YourBusinessService(IGraphServiceClient graphClient)
    {
        _graphClient = graphClient;
    }

    public async Task<User> GetUserByMobilePhoneAsync(string mobilePhone)
    {
        return (await _graphClient.Users.Request().Filter($"displayName eq '{mobilePhone}'").GetAsync()).FirstOrDefault();
    }
}

单元测试实现逻辑

由于Graph SDK的调用是链式结构,需要逐层配置Mock返回值,请求链对应接口层级为:IGraphServiceClient → IGraphUsersRequestBuilder → IGraphUsersCollectionRequest,完整xUnit测试代码示例如下:

using Moq;
using Xunit;
using Microsoft.Graph;

public class YourBusinessServiceTests
{
    [Fact]
    public async Task GetUserByMobilePhoneAsync_ReturnsCorrectUser_WhenUserExists()
    {
        // 1. 准备测试数据
        var testMobilePhone = "13800138000";
        var expectedUser = new User { DisplayName = testMobilePhone, Id = "test-user-id" };
        var mockUserPage = new GraphServiceUsersCollectionPage
        {
            new User { DisplayName = "other-user" },
            expectedUser
        };

        // 2. 逐层配置Mock链
        // Mock 集合请求实例
        var mockUsersRequest = new Mock<IGraphUsersCollectionRequest>();
        // 配置Filter方法:匹配过滤条件后返回请求自身,不需要校验参数时可替换为It.IsAny<string>()
        mockUsersRequest.Setup(r => r.Filter(It.Is<string>(f => f == $"displayName eq '{testMobilePhone}'")))
            .Returns(mockUsersRequest.Object);
        // 配置GetAsync方法返回模拟的用户集合
        mockUsersRequest.Setup(r => r.GetAsync())
            .ReturnsAsync(mockUserPage);

        // Mock 用户请求构建器
        var mockUsersBuilder = new Mock<IGraphUsersRequestBuilder>();
        mockUsersBuilder.Setup(b => b.Request())
            .Returns(mockUsersRequest.Object);

        // Mock Graph客户端实例
        var mockGraphClient = new Mock<IGraphServiceClient>();
        mockGraphClient.Setup(c => c.Users)
            .Returns(mockUsersBuilder.Object);

        // 3. 注入Mock实例执行业务逻辑
        var businessService = new YourBusinessService(mockGraphClient.Object);
        var result = await businessService.GetUserByMobilePhoneAsync(testMobilePhone);

        // 4. 断言结果
        Assert.NotNull(result);
        Assert.Equal(expectedUser.Id, result.Id);
        // 可选:验证Filter确实传入了正确的参数
        mockUsersRequest.Verify(r => r.Filter(It.Is<string>(f => f == $"displayName eq '{testMobilePhone}'")), Times.Once);
    }
}

注意事项

  • 如果不需要校验Filter的传参是否正确,可以把Filter的配置参数改为It.IsAny<string>(),适配任意过滤条件
  • 如果你使用的是v5及以上版本的Microsoft Graph SDK,请求写法有调整,对应的Mock接口也需要同步更换为新版的接口定义
  • 不要直接MockGraphServiceClient实现类,始终Mock其暴露的IGraphServiceClient接口,可以避免很多内部实现导致的Mock失败问题

内容的提问来源于stack exchange,提问作者Davide Boldrin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 05:36:06