3

请考虑如下所示的代码。通过调用 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());
}
4

2 回答 2

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");
}
于 2013-03-21T08:16:38.867 回答
1

您的模型(DTO)正在填充自身(数据访问)。这对于一个班级来说太多了。通常当你问自己“我到底该如何测试这个”时,是时候进行重构了。创建一个单独的数据访问类:

BrandsViewModel viewModel = new BrandsViewModel();
var brandAccess = new BrandsDataAccess();
viewModel.Brands = await brandAccess.GetAllBrands();
Assert.IsTrue(viewModel.Brands.Any());

现在你可以测试了BrandsDataAccess.GetAllBrands()

于 2013-03-21T08:00:03.113 回答