How to write service test for UpdateAsync in Microsoft Graph API(在单个请求中将多个成员添加到组)
How to write service test for UpdateAsync in Microsoft Graph API (Add multiple members to a group in a single request)
我正在使用 Microsoft Graph Api 客户端并执行向组添加成员。
我已成功达到要求。但是当我为我的服务编写测试时 class 不知道什么以及如何验证它。
我是 API 开发人员的初学者,也是 Microsoft Graph API 的初学者。以下是我的代码,看看并 post 您的建议和意见。可能会有帮助。
服务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);
}
}
服务测试:
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();
}
}
我想验证 _graphServiceClientMock AdditionalData 值 == 模拟组 AdditionalData 值,它像上面一样在 _graphServiceClientMock 中调用一次。任何人对此都有想法。请post提前comments.Thanks。
基于被测对象和提供的被测成员的简单性,以下示例演示了如何对其进行隔离测试,
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
}
}
查看代码注释以了解如何执行测试以验证预期行为。
所使用的 FluentAssertions 的直观性质也应该有助于理解所断言的内容
我正在使用 Microsoft Graph Api 客户端并执行向组添加成员。
我已成功达到要求。但是当我为我的服务编写测试时 class 不知道什么以及如何验证它。
我是 API 开发人员的初学者,也是 Microsoft Graph API 的初学者。以下是我的代码,看看并 post 您的建议和意见。可能会有帮助。
服务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);
}
}
服务测试:
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();
}
}
我想验证 _graphServiceClientMock AdditionalData 值 == 模拟组 AdditionalData 值,它像上面一样在 _graphServiceClientMock 中调用一次。任何人对此都有想法。请post提前comments.Thanks。
基于被测对象和提供的被测成员的简单性,以下示例演示了如何对其进行隔离测试,
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
}
}
查看代码注释以了解如何执行测试以验证预期行为。
所使用的 FluentAssertions 的直观性质也应该有助于理解所断言的内容