C# 如何测试异步void方法 请考虑下面的代码。通过调用GetBrands,酒店品牌将被分配适当的数据 public class BrandsViewModel : ViewModelBase { private IEnumerable<Brand> _brands; public IEnumerable<Brand> Brands { get { return _brands; } set { SetProperty(ref _brands, value); } } public async void GetBrands() { // ...... Brands = await _dataHelper.GetFavoriteBrands(); // ...... } }
您的模型(DTO)正在填充自身(数据访问)。这对一个班级来说太多了。通常,当你问自己“我到底该如何测试它”时,是时候进行重构了。创建单独的数据访问类:C# 如何测试异步void方法 请考虑下面的代码。通过调用GetBrands,酒店品牌将被分配适当的数据 public class BrandsViewModel : ViewModelBase { private IEnumerable<Brand> _brands; public IEnumerable<Brand> Brands { get { return _brands; } set { SetProperty(ref _brands, value); } } public async void GetBrands() { // ...... Brands = await _dataHelper.GetFavoriteBrands(); // ...... } },c#,unit-testing,async-await,C#,Unit Testing,Async Await,您的模型(DTO)正在填充自身(数据访问)。这对一个班级来说太多了。通常,当你问自己“我到底该如何测试它”时,是时候进行重构了。创建单独的数据访问类: BrandsViewModel viewModel = new BrandsViewModel(); var brandAccess = new BrandsDataAccess(); viewModel.Brands = await brandAccess.GetAllBrands(); Assert.IsTrue(viewModel.Bran
BrandsViewModel viewModel = new BrandsViewModel();
var brandAccess = new BrandsDataAccess();
viewModel.Brands = await brandAccess.GetAllBrands();
Assert.IsTrue(viewModel.Brands.Any());
现在,您可以测试
BrandsDataAccess.GetAllBrands()
这里的简单答案是:不要将其设置为异步void
。事实上,永远不要将某个东西设置为异步void
,除非它必须作为事件处理程序工作。async void
丢失的东西正是您希望在这里测试的东西(可能是真正的代码)
改为使用async Task
方法,您现在可以等待完成(超时)/添加延续,并检查它是成功退出还是异常退出
这是一个单词的更改,更改为:
public async Task GetBrands()
{
// ......
Brands = await _dataHelper.GetFavoriteBrands();
// ......
}
然后在测试中:
[TestMethod]
public async Task AllBrandsTest()
{
BrandsViewModel viewModel = new BrandsViewModel();
var task = viewModel.GetBrands();
Assert.IsTrue(task.Wait(YOUR_TIMEOUT), "failed to load in time");
Assert.IsTrue(viewModel.Brands.Any(), "no brands");
}
请阅读/查看:它基本上说:除了事件处理程序之外,不要使用
async void
。@DanielHilgarth谢谢你,Daniel。我重构了我的代码,它就像一个魔咒一样工作。如果你没有在测试中使用wait
,为什么要保持测试async
?@svick这是OP的问题,谁也没有wait
:)@svick我的错。我已经更正了我的测试代码。如果方法中没有等待,就没有必要保持异步。async
去了哪里?我的意思是:原来的代码是异步的,你的不是,所以我认为它不是一个好的替代品。@svick重要的是原则,而不是实现。请参见编辑。@CodeCaster请进一步解释您的观点好吗?就单一责任原则而言,我认为在同一类中填充自己的属性是可以接受的。不是吗?@Shinbo不,数据传输对象(视图模型)不应该与数据访问有关。@CodeCaster感谢您的澄清。如果DTO包含数据访问逻辑,会产生什么副作用?
[TestMethod]
public async Task AllBrandsTest()
{
BrandsViewModel viewModel = new BrandsViewModel();
var task = viewModel.GetBrands();
Assert.IsTrue(task.Wait(YOUR_TIMEOUT), "failed to load in time");
Assert.IsTrue(viewModel.Brands.Any(), "no brands");
}