测试 属性 由异步方法设置
Testing property set by async method
我尝试使用包含异步方法的 NUnit 测试 class。我不知道如何以正确的方式做到这一点。
我有一个 class 看起来像这样:
public class EditorViewModel:INotifyPropertyChanged
{
public void SetIdentifier(string identifier)
{
CalcContentAsync();
}
private async void CalcContentAsync()
{
await SetContentAsync();
DoSomething();
}
private async Task SetContentAsync()
{
Content = await Task.Run<object>(() => CalculateContent());
RaisePropertyChanged("Content");
}
public object Content { get; private set; }
...
}
如何在 NUnit 中编写测试,检查 Content-属性 是否设置为正确的值?我想做这样的事情:
[Test]
public void Content_WhenModifierIsXXX_ReturnsSomeViewModel()
{
var viewModel = new EditorViewModel();
viewModel.SetIdentifier("XXX");
Assert.That(viewModel.Content, Is.InstanceOf<ISomeContentViewModel>());
}
但这不起作用。因为断言之前异步代码还没有执行。
你的SetIdentifier
方法也是async
(或者你需要async
因为你在里面等待操作。然后你的方法看起来像下一个:
public async Task SetIdentifier(string identifier)
{
await SetContentAsync();
DoSomething();
}
现在您可以在单元测试中等待它:
[Test]
public async Task Content_WhenModifierIsXXX_ReturnsSomeViewModel()
{
var viewModel = new EditorViewModel();
await viewModel.SetIdentifier("XXX");
Assert.That(viewModel.Content, Is.InstanceOf<ISomeContentViewModel>());
}
您还可以使用变通方法以同步方式调用您的测试:
[Test]
public async Task Content_WhenModifierIsXXX_ReturnsSomeViewModel()
{
Task.Run(async () =>
{
var viewModel = new EditorViewModel();
await viewModel.SetIdentifier("XXX");
Assert.That(viewModel.Content, Is.InstanceOf<ISomeContentViewModel>());
}).GetAwaiter().GetResult();
}
通过 MSDN Magazine.
使用 async
时,您应该始终 return 一个任务。否则它将是 "fire and forget",并且您绝对无法与 Task
.
进行交互
因此您应该将 SetIdentifier 的签名更改为 return a Task
,如下所示:
public async Task SetIdentifier(string identifier)
{
await SetContentAsync();
DoSomething();
}
然后就可以在测试中等待操作完成:
[Test]
public async void Content_WhenModifierIsXXX_ReturnsSomeViewModel()
{
var viewModel = new EditorViewModel();
await viewModel.SetIdentifier("XXX");
Assert.That(viewModel.Content, Is.InstanceOf<ISomeContentViewModel>());
}
或者,如果您的测试运行器不支持 async
:
[Test]
public void Content_WhenModifierIsXXX_ReturnsSomeViewModel()
{
var viewModel = new EditorViewModel();
viewModel.SetIdentifier("XXX").Wait();
Assert.That(viewModel.Content, Is.InstanceOf<ISomeContentViewModel>());
}
我尝试使用包含异步方法的 NUnit 测试 class。我不知道如何以正确的方式做到这一点。
我有一个 class 看起来像这样:
public class EditorViewModel:INotifyPropertyChanged
{
public void SetIdentifier(string identifier)
{
CalcContentAsync();
}
private async void CalcContentAsync()
{
await SetContentAsync();
DoSomething();
}
private async Task SetContentAsync()
{
Content = await Task.Run<object>(() => CalculateContent());
RaisePropertyChanged("Content");
}
public object Content { get; private set; }
...
}
如何在 NUnit 中编写测试,检查 Content-属性 是否设置为正确的值?我想做这样的事情:
[Test]
public void Content_WhenModifierIsXXX_ReturnsSomeViewModel()
{
var viewModel = new EditorViewModel();
viewModel.SetIdentifier("XXX");
Assert.That(viewModel.Content, Is.InstanceOf<ISomeContentViewModel>());
}
但这不起作用。因为断言之前异步代码还没有执行。
你的SetIdentifier
方法也是async
(或者你需要async
因为你在里面等待操作。然后你的方法看起来像下一个:
public async Task SetIdentifier(string identifier)
{
await SetContentAsync();
DoSomething();
}
现在您可以在单元测试中等待它:
[Test]
public async Task Content_WhenModifierIsXXX_ReturnsSomeViewModel()
{
var viewModel = new EditorViewModel();
await viewModel.SetIdentifier("XXX");
Assert.That(viewModel.Content, Is.InstanceOf<ISomeContentViewModel>());
}
您还可以使用变通方法以同步方式调用您的测试:
[Test]
public async Task Content_WhenModifierIsXXX_ReturnsSomeViewModel()
{
Task.Run(async () =>
{
var viewModel = new EditorViewModel();
await viewModel.SetIdentifier("XXX");
Assert.That(viewModel.Content, Is.InstanceOf<ISomeContentViewModel>());
}).GetAwaiter().GetResult();
}
通过 MSDN Magazine.
使用 async
时,您应该始终 return 一个任务。否则它将是 "fire and forget",并且您绝对无法与 Task
.
因此您应该将 SetIdentifier 的签名更改为 return a Task
,如下所示:
public async Task SetIdentifier(string identifier)
{
await SetContentAsync();
DoSomething();
}
然后就可以在测试中等待操作完成:
[Test]
public async void Content_WhenModifierIsXXX_ReturnsSomeViewModel()
{
var viewModel = new EditorViewModel();
await viewModel.SetIdentifier("XXX");
Assert.That(viewModel.Content, Is.InstanceOf<ISomeContentViewModel>());
}
或者,如果您的测试运行器不支持 async
:
[Test]
public void Content_WhenModifierIsXXX_ReturnsSomeViewModel()
{
var viewModel = new EditorViewModel();
viewModel.SetIdentifier("XXX").Wait();
Assert.That(viewModel.Content, Is.InstanceOf<ISomeContentViewModel>());
}