C# 如何在Microsoft Graph API中为UpdateSync编写服务测试(在一个请求中向一个组添加多个成员)
我正在使用Microsoft Graph Api客户端并执行向组中添加成员 文件如下: 我成功地达到了要求。但当我为我的服务类编写测试时,却不知道该做什么以及如何验证它 我是API开发的初学者,也是Microsoft Graph API的初学者。下面是我的代码,请看一下并发表您的建议和评论。这可能会有帮助 服务类别:C# 如何在Microsoft Graph API中为UpdateSync编写服务测试(在一个请求中向一个组添加多个成员),c#,azure,unit-testing,microsoft-graph-api,servicetestcase,C#,Azure,Unit Testing,Microsoft Graph Api,Servicetestcase,我正在使用Microsoft Graph Api客户端并执行向组中添加成员 文件如下: 我成功地达到了要求。但当我为我的服务类编写测试时,却不知道该做什么以及如何验证它 我是API开发的初学者,也是Microsoft Graph API的初学者。下面是我的代码,请看一下并发表您的建议和评论。这可能会有帮助 服务类别: public class UserGroupService : IUserGroupService { private readonly IGraphServiceClie
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类UserGroupService:IUserGroupService
{
专用只读IGraphServiceClient _graphServiceClient;
公共用户组服务(IGraphServiceClient graphServiceClient)
{
_graphServiceClient=graphServiceClient;
}
公共异步任务AddAsync(字符串groupId,IList userid)
{
var组=新组
{
AdditionalData=新字典()
{
{"members@odata.bind,用户ID。选择(x=>$)https://graph.microsoft.com/v1.0/directoryObjects/{x} }
}
};
wait _graphServiceClient.Groups[groupId].Request().UpdateSync(组);
}
}
服务测试:
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();
}
}
公共类UserGroupServiceTests
{
专用只读设备_Fixture=新设备();
private readonly Mock_graphServiceClientMock=new Mock();
私有只读IUserGroupService\u userGroupService;
公共UserGroupServiceTests()
{
_userGroupService=newusergroupservice(_graphServiceClientMock.Object);
}
//设置GraphClientMock
私有void SetupGraphClientMock(字符串组ID、IList用户ID、组组组)
{
var groupRequest=new Mock();
var groupRequestBuilder=new Mock();
Setup(x=>x.UpdateAsync(组));
groupRequestBuilder.Setup(x=>x.Request()).Returns(groupRequest.Object);
_graphServiceClientMock.Setup(x=>x.Groups[groupId])。返回(groupRequestBuilder.Object);
}
[事实]
公共异步任务AddAsync\u在服务成功时提供验证输入\u AddAsyncCalledOnce()
{
客观结果;
var groupId=_fixture.Create();
var userIds=_fixture.Create();
var dictionary=_fixture.Create();
字典。添加(“members@odata.bind,用户ID。选择(x=>$)https://graph.microsoft.com/v1.0/directoryObjects/{x} ”);
var group=_fixture.Build().With(s=>s.AdditionalData,dictionary)。省略AutoProperties().Create();
SetupGraphClientMock(组ID、用户ID、组);
wait\u userGroupService.AddAsync(groupId,userid);
//待办事项
//需要验证_GraphServiceClientMockAdditionalData value==模拟组AdditionalData值,该值在_graphServiceClientMock中调用一次。
//下面的实现使用返回bool的TryGetValue完成,我真的很害怕使用bool值编写测试并进行比较,我觉得这不是编写测试的正确方法。
_GraphServiceClientLock.Verify(m=>m.Groups[groupId].Request().UpdateSync(It.Is(x=>x.AdditionalData.TryGetValue)()members@odata.bind,输出结果)=组。附加数据。TryGetValue('members@odata.bind“,out result”)),次。一次);
_graphServiceClientLock.VerifyNoOtherCalls();
}
}
我想验证_graphserviceclientmockadditionaldata value==模拟组AdditionalData value,该值在_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 = "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
}
}
公共类UserGroupServiceTests{
[事实]
公共异步任务AddAsync\u在服务成功时提供验证输入\u AddAsyncCalledOnce(){
//安排
字符串groupId=“123456”;
IList userIds=new[]{“a”、“b”、“c”}.ToList();
字符串expectedKey=”members@odata.bind";
IEnumerable expectedValues=用户标识
.选择(x=>$”https://graph.microsoft.com/v1.0/directoryObjects/{x} ”;
组=空;
Mock clientMock=新建Mock();
clientMock
.Setup(x=>x.Groups[groupId].Request().UpdateAsync(It.IsAny())
.Callback((Group g)=>Group=g)//捕获传递的组以便稍后断言
.ReturnsAsync(组)//以允许异步流
.可验证();
IUserGroupService\u userGroupService=newusergroupservice(clientMock.Object);
//表演
wait\u userGroupService.AddAsync(groupId,userid);
//断言
clientMock.Verify();//是否满足可验证表达式
clientMock.VerifyNoOtherCalls();
//使用FluentAssertions断言捕获的组
group.Should().NotBeNull();//是否传递了一个组
group.AdditionalData.Should().NotBeNull()//它有数据吗
.And.ContainKey(expectedKey);//数据是否具有预期的密钥
(group.AdditionalData[expectedKey]作为IEnumerable)
.Should().beequivalento(expectedValues);//是预期的值
}
}
查看代码注释以了解如何执行测试以验证预期行为
所用FluentAssertions的直观性质也有助于理解所断言的内容哇……太好了!!非常感谢,恩科西。它真的帮助了我。