简体   繁体   中英

How to write service test for UpdateAsync in Microsoft Graph API (Add multiple members to a group in a single request)

I am using Microsoft Graph Api client and performing add members to group.

Docs here:- https://docs.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

I have successfully achieved the requirement. But when come to write test for my service class having no clue what and how to verify it.

I am beginner to the API dev and also with Microsoft Graph API. Below are my codes, Take a look and post your suggestions and comments. It might be helpful.

Service Class:

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>()
            {
                {"members@odata.bind", userIds.Select(x => $"https://graph.microsoft.com/v1.0/directoryObjects/{x}") }
            }
        };

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

ServiceTest:

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("members@odata.bind", 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("members@odata.bind", out result) == group.AdditionalData.TryGetValue("members@odata.bind", out result))), Times.Once);
            _graphServiceClientMock.VerifyNoOtherCalls();
        }
    }

I wants to verify _graphServiceClientMock AdditionalData value == mocking group AdditionalData value which is called once in _graphServiceClientMock like the above. Anyone have idea on this. Please post your comments.Thanks in Advance.

Based on the subject under test and the simplicity of the provided member under test the following example demonstrates how it can be tested in isolation,

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 = "members@odata.bind";
        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
    }
}

Review the code comments to get an understanding of how the test was exercised to verify the expected behavior.

The intuitive nature of the used FluentAssertions should also help in understanding what is being asserted

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM