c# - 如何在 Microsoft Graph API 中为 UpdateAsync 编写服务测试(在单个请求中将多个成员添加到组)

标签 c# azure unit-testing microsoft-graph-api servicetestcase

我正在使用 Microsoft Graph Api 客户端并执行向组添加成员的操作。

此处的文档:- https://learn.microsoft.com/en-us/graph/api/group-post-members?view=graph-rest-1.0&tabs=csharp#example-2-add-multiple-members-to-a-group-in-a-single-request

我已经成功达到要求了。但是当我为我的服务类编写测试时,不知道验证什么以及如何验证它。

我是 API 开发和 Microsoft Graph API 的初学者。以下是我的代码,请查看并发表您的建议和评论。这可能会有所帮助。

服务等级:

public class UserGroupService : IUserGroupService
{
    private readonly IGraphServiceClient _graphServiceClient;

    public UserGroupService(IGraphServiceClient graphServiceClient)
    {
        _graphServiceClient = graphServiceClient;
    }
    
    public async Task AddAsync(string groupId, IList<string> userIds)
    {
        var group = new Group
        {
            AdditionalData = new Dictionary<string, object>()
            {
                {"<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="e9848c848b8c9b9aa9868d889d88c78b80878d" rel="noreferrer noopener nofollow">[email protected]</a>", userIds.Select(x => $"https://graph.microsoft.com/v1.0/directoryObjects/{x}") }
            }
        };

        await _graphServiceClient.Groups[groupId].Request().UpdateAsync(group);
    }
}

服务测试:

public class UserGroupServiceTests
    {
        private readonly Fixture _fixture = new Fixture();
        private readonly Mock<IGraphServiceClient> _graphServiceClientMock = new Mock<IGraphServiceClient>();
        private readonly IUserGroupService _userGroupService;

        public UserGroupServiceTests()
        {
            _userGroupService = new UserGroupService(_graphServiceClientMock.Object);
        }
        
        // Settingup GraphClientMock
        private void SetupGraphClientMock(string groupId, IList<string> userIds, Group group)
        {
            var groupRequest = new Mock<IGroupRequest>();

            var groupRequestBuilder = new Mock<IGroupRequestBuilder>();

            groupRequest.Setup(x => x.UpdateAsync(group));

            groupRequestBuilder.Setup(x => x.Request()).Returns(groupRequest.Object);

            _graphServiceClientMock.Setup(x => x.Groups[groupId]).Returns(groupRequestBuilder.Object);
        }
        
        [Fact]
        public async Task AddAsync_GivenValidInput_WhenServiceSuccessful_AddAsyncCalledOnce()
        {
            object result;
            var groupId = _fixture.Create<string>();
            var userIds = _fixture.Create<IList<string>>();
            var dictionary = _fixture.Create<Dictionary<string, object>>();
            dictionary.Add("<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="5439313936312627143b303520357a363d3a30" rel="noreferrer noopener nofollow">[email protected]</a>", userIds.Select(x => $"https://graph.microsoft.com/v1.0/directoryObjects/{x}"));
            var group = _fixture.Build<Group>().With(s => s.AdditionalData, dictionary).OmitAutoProperties().Create();

            SetupGraphClientMock(groupId, userIds, group);

            await _userGroupService.AddAsync(groupId, userIds);

            //TODO  
            // Need to verify _graphServiceClientMock AdditionalData value == mocking group AdditionalData value which is called once in _graphServiceClientMock.
            // Below implementation done using TryGetValue which return bool, I am really afraid to write test using bool value and compare and I feel its not a right way to write test.
            _graphServiceClientMock.Verify(m => m.Groups[groupId].Request().UpdateAsync(It.Is<Group>(x => x.AdditionalData.TryGetValue("<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="8ce1e9e1eee9feffcce3e8edf8eda2eee5e2e8" rel="noreferrer noopener nofollow">[email protected]</a>", out result) == group.AdditionalData.TryGetValue("<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="d1bcb4bcb3b4a3a291beb5b0a5b0ffb3b8bfb5" rel="noreferrer noopener nofollow">[email protected]</a>", out result))), Times.Once);
            _graphServiceClientMock.VerifyNoOtherCalls();
        }
    }

我想验证 _graphServiceClientMock DifferentialData 值 == 模拟组AdditionalData 值,该值在 _graphServiceClientMock 中调用一次,如上所述。任何人对此都有想法。请发表您的评论。提前致谢。

最佳答案

根据被测试的主题和所提供的被测试成员的简单性,以下示例演示了如何单独测试它,

public class UserGroupServiceTests {

    [Fact]
    public async Task AddAsync_GivenValidInput_WhenServiceSuccessful_AddAsyncCalledOnce() {
        //Arrange            
        string groupId = "123456";
        IList<string> userIds = new[] { "a", "b", "c" }.ToList();
        string expectedKey = "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="e38e868e81869190a38c87829782cd818a8d87" rel="noreferrer noopener nofollow">[email protected]</a>";
        IEnumerable<string> expectedValues = userIds
            .Select(x => $"https://graph.microsoft.com/v1.0/directoryObjects/{x}");
        Group group = null;

        Mock<IGraphServiceClient> clientMock = new Mock<IGraphServiceClient>();
        clientMock
            .Setup(x => x.Groups[groupId].Request().UpdateAsync(It.IsAny<Group>()))
            .Callback((Group g) => group = g) //Capture passed group for assertion later
            .ReturnsAsync(group) //To allow async flow
            .Verifiable();

        IUserGroupService _userGroupService = new UserGroupService(clientMock.Object);

        //Act
        await _userGroupService.AddAsync(groupId, userIds);

        //Assert
        clientMock.Verify(); //have verifiable expressions been met
        clientMock.VerifyNoOtherCalls();

        //Using FluentAssertions to assert captured group
        group.Should().NotBeNull();//was a group passed
        group.AdditionalData.Should().NotBeNull()// did it have data
            .And.ContainKey(expectedKey);//and did the data have expected key
        (group.AdditionalData[expectedKey] as IEnumerable<string>)
            .Should().BeEquivalentTo(expectedValues);//are values as expected
    }
}

查看代码注释,了解如何执行测试来验证预期行为。

所使用的 FluentAssertions 的直观性质也应该有助于理解所断言的内容

关于c# - 如何在 Microsoft Graph API 中为 UpdateAsync 编写服务测试(在单个请求中将多个成员添加到组),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65969957/

相关文章:

delphi - 为 Mock 提供数据以进行单元测试

ruby-on-rails - 使用单元测试、Rspec、Cucumber 和 Capybara 是否有意义?

c# - 在 Datagridview 中插入时出错

Azure ARM 模板 - ssh 公钥和私钥

c# - 自动滚动到 WinRT 应用程序中的 ListView 底部

azure - 尝试发布 Azure API。 VS2017似乎没有最新的Azure SDK

Azure:当网络故障时收到通知

unit-testing - 如何创建在另一个配方中定义的虚拟资源而不在测试运行中包含另一个配方?

c# - 如何将具有许多功能的大型 WCF 服务导入到 VS 2010 中?

c# - ASP.NET Web API Post 方法错误