c# – 如何正确编写异步XUnit测试?
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了c# – 如何正确编写异步XUnit测试?,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4478字,纯文字阅读大概需要7分钟。
内容图文
![c# – 如何正确编写异步XUnit测试?](/upload/InfoBanner/zyjiaocheng/774/35daef67b7de419193603682723ad15e.jpg)
我正在使用异步xUnit测试,我注意到不一致的传递行为:
public async Task FetchData()
{
//Arrange
var result = await arrangedService.FetchDataAsync().ConfigureAwait(false);
//Assert
}
我已经完成了此测试执行的调用堆栈,并验证了我的所有库代码都在每个任务之后调用.ConfigureAwait(false).但是,尽管如此,在执行全部运行时,此测试和其他测试将间歇性地失败,但是当我在调试器上完成时,会通过断言和手动检查.很明显,我没有正确地做某事.我已经尝试在测试本身中删除对ConfigureAwait(false)的调用,以防有特殊的xUnit同步上下文,但它没有改变任何东西.以一致的方式测试异步代码的最佳方法是什么?
编辑好的,这是我尝试创建一个运行的代码的超简化示例,以提供正在发生的事情的示例:
using Graph = Microsoft.Azure.ActiveDirectory.GraphClient;
public async Task FetchData()
{
var adUsers = baseUsers //IEnumerable<Graph.User>
.Cast<Graph.IUser>()
.ToList();
var nextPageUsers = Enumerable
.Range(GoodIdMin, GoodIdMax)
.Select(number => new Graph.User
{
Mail = (-number).ToString()
})
.Cast<Graph.IUser>()
.ToList();
var mockUserPages = new Mock<IPagedCollection<Graph.IUser>>();
mockUserPages
.Setup(pages => pages.MorePagesAvailable)
.Returns(true);
mockUserPages
.Setup(pages => pages.CurrentPage)
.Returns(new ReadOnlyCollection<Graph.IUser>(adUsers));
mockUserPages
.Setup(pages => pages.GetNextPageAsync())
.ReturnsAsync(mockUserPages.Object)
.Callback(() =>
{
mockUserPages
.Setup(pages => pages.CurrentPage)
.Returns(new ReadOnlyCollection<Graph.IUser>(nextPageUsers));
mockUserPages
.Setup(pages => pages.MorePagesAvailable)
.Returns(false);
});
var mockUsers = new Mock<Graph.IUserCollection>();
mockUsers
.Setup(src => src.ExecuteAsync())
.ReturnsAsync(mockUserPages.Object);
var mockGraphClient = new Mock<Graph.IActiveDirectoryClient>();
mockGraphClient
.Setup(src => src.Users)
.Returns(mockUsers.Object);
var mockDbUsers = CreateBasicMockDbSet(baseUsers.Take(10)
.Select(user => new User
{
Mail = user.Mail
})
.AsQueryable());
var mockContext = new Mock<MyDbContext>();
mockContext
.Setup(context => context.Set<User>())
.Returns(mockDbUsers.Object);
var mockGraphProvider = new Mock<IGraphProvider>();
mockGraphProvider
.Setup(src => src.GetClient()) //Creates an IActiveDirectoryClient
.Returns(mockGraphClient.Object);
var getter = new UserGetter(mockContext.Object, mockGraphProvider.Object);
var result = await getter.GetData().ConfigureAwait(false);
Assert.True(result.Success); //Not the actual assert
}
这是在var result = … line上执行的代码:
public UserGetterResult GetData()
{
var adUsers = await GetAdUsers().ConfigureAwait(false);
var dbUsers = Context.Set<User>().ToList(); //This is the injected context from before
return new UserGetterResult //Just a POCO
{
AdUsers = adUsers
.Except(/*Expression that indicates whether
or not this user is in the database*/)
.ProjectTo<User>()
.ToList(),
DbUsers = dbUsers.ProjectTo<User>().ToList() //Automapper 6.1.1
};
}
private async Task<List<User>> GetAdUsers()
{
var userPages = await client //Injected IActiveDirectoryClient from before
.Users
.ExecuteAsync()
.ConfigureAwait(false);
var users = userPages.CurrentPage.ToList();
while(userPages.MorePagesAvailable)
{
userPages = await userPages.GetNextPageAsync().ConfigureAwait(false);
users.AddRange(userPages.CurrentPage);
}
return users;
}
代码的目的是获取AD中但不是数据库的用户列表以及数据库中的用户列表.
编辑编辑因为我忘了在原始更新中包含它,所以在调用`IUserCollection.ExecuteAsync()时都会发生错误.
解决方法:
IUserCollection.ExecuteAsync()似乎是根据原始帖子中显示的内容正确配置的.
现在关注以下方法……
private async Task<List<User>> GetAdUsers() {
var userPages = await client //Injected IActiveDirectoryClient from before
.Users
.ExecuteAsync()
.ConfigureAwait(false);
var users = userPages.CurrentPage.ToList();
while(userPages.MorePagesAvailable) {
userPages = await userPages.GetNextPageAsync().ConfigureAwait(false);
users.AddRange(userPages.CurrentPage);
}
return users;
}
我关心如何在模拟中设置用户页面.鉴于GetAdUsers方法的流程,最好使用SetupSequence来模拟重复调用CurrentPage和MorePagesAvailable.
var mockUserPages = new Mock<IPagedCollection<Graph.IUser>>();
mockUserPages
.SetupSequence(_ => _.MorePagesAvailable)
.Returns(true) // First time called to enter while loop
.Returns(false); // Second time called to exit while loop
mockUserPages
.SetupSequence(_ => _.CurrentPage)
.Returns(new ReadOnlyCollection<Graph.IUser>(adUsers)) // First time called to get List
.Returns(new ReadOnlyCollection<Graph.IUser>(nextPageUsers)); // Second time called to get next page
mockUserPages
.Setup(pages => pages.GetNextPageAsync())
.ReturnsAsync(mockUserPages.Object); // No need for callback
内容总结
以上是互联网集市为您收集整理的c# – 如何正确编写异步XUnit测试?全部内容,希望文章能够帮你解决c# – 如何正确编写异步XUnit测试?所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。