请考虑以下代码。通过调用GetBrands,将为属性Brands分配适当的数据。
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();
// ......
}
}
但如果按下图所示进行测试,则测试失败。如何等待方法GetBrands中的异步调用?
[TestMethod]
public void AllBrandsTest()
{
BrandsViewModel viewModel = new BrandsViewModel();
viewModel.GetBrands();
Assert.IsTrue(viewModel.Brands.Any());
}
答案 0 :(得分:8)
这里的简单答案是:不要使它成为async void
。事实上,除非绝对必须作为事件处理程序工作,否则不要永远创建async 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");
}
答案 1 :(得分:1)
您的模型(DTO)正在自行填充(数据访问)。这对于一个班级来说太过分了。通常当你问自己“我怎么能测试这个”时,就是重构的时候了。创建一个单独的数据访问类:
BrandsViewModel viewModel = new BrandsViewModel();
var brandAccess = new BrandsDataAccess();
viewModel.Brands = await brandAccess.GetAllBrands();
Assert.IsTrue(viewModel.Brands.Any());
现在您可以测试BrandsDataAccess.GetAllBrands()
。