Fluent-ASsertions ShouldRaisePropertyChangeFor 不适用于异步任务?
Posted
技术标签:
【中文标题】Fluent-ASsertions ShouldRaisePropertyChangeFor 不适用于异步任务?【英文标题】:Fluent-ASsertions ShouldRaisePropertyChangeFor does not work for async Tasks? 【发布时间】:2017-04-15 05:42:21 【问题描述】:我有一个实现INotifyPropertyChanged
的简单类,我在另一个线程上调用属性更改,我很难让FluentAsserts
看到propertyChanged
被调用。如果我在 async Task
方法中使用 Task.Delay
似乎不会发生这种情况。但如果我只是让线程休眠,它就可以了。
SimpleNotify
类:
namespace FluentAssertPropertyThreads
class SimpleNotify : System.ComponentModel.INotifyPropertyChanged
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
private void onChange(string name)
this.PropertyChanged?.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs(name));
private int count = 0;
public int Count
get
return this.count;
set
if (this.count != value)
this.count = value;
this.onChange(nameof(this.Count));
这是我的单元测试:
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace FluentAssertPropertyThreads
[TestClass]
public class UnitTest1
private SimpleNotify simpleNotify;
private int notifyCount;
private void bumpCount()
this.simpleNotify.Count++;
private void SimpleNotify_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
SimpleNotify simpleNotify = sender as SimpleNotify;
if (simpleNotify == null)
throw new ArgumentNullException(nameof(sender), "sender should be " + nameof(SimpleNotify));
if (e.PropertyName.Equals(nameof(SimpleNotify.Count), StringComparison.InvariantCultureIgnoreCase))
this.notifyCount++;
[TestInitialize]
public void TestSetup()
this.notifyCount = 0;
this.simpleNotify = new SimpleNotify();
this.simpleNotify.PropertyChanged += SimpleNotify_PropertyChanged;
this.simpleNotify.MonitorEvents();
Thread thread = new Thread(this.bumpCount)
IsBackground = true,
Name = @"My Background Thread",
Priority = ThreadPriority.Normal
;
thread.Start();
[TestMethod]
public async Task TestMethod1()
await Task.Delay(100);
this.notifyCount.Should().Be(1); //this passes, so I know that my notification has be executed.
this.simpleNotify.ShouldRaisePropertyChangeFor(x => x.Count); //but this fails, saying that I need to be monitoring the events (which I am above)
[TestMethod]
public void TestMethod2()
Thread.Sleep(100);
this.notifyCount.Should().Be(1); //this passes, so I know that my notification has be executed.
this.simpleNotify.ShouldRaisePropertyChangeFor(x => x.Count); //this passes as I expected
确切的错误是:
System.InvalidOperationException:对象没有被监视事件或已被垃圾收集。使用 MonitorEvents() 扩展方法开始监控事件。
我不明白 MonitorEvents
会在意我使用 await 还是 Thread.Sleep
。我错过了什么?我知道await
离开该方法并返回,而Thread.Sleep
没有。
所以当它在等待期间离开TestMethod1
时,它正在处理FluentAsserts
用来跟踪属性的对象?可以吗?应该是?
【问题讨论】:
【参考方案1】:是的,事情就像你说的那样:await
暂停当前方法的执行并创建一个状态机以在Delay
完成后返回该方法。但是调用者(一个 UnitTest 引擎)并不期望您的测试是异步的,而是简单地结束执行,从而导致对象的处置。
Stephen Cleary 写了一个出色的 MSDN article about Unit testing and async/await
keywords,您可能应该将您的代码移到返回 Task
的方法中,然后等待所有这些都在测试中,如下所示:
async Task Testing()
await Task.Delay(100);
this.notifyCount.Should().Be(1);
this.simpleNotify.ShouldRaisePropertyChangeFor(x => x.Count);
[TestMethod]
public async Task TestMethod1()
await Testing();
但这仍然可能会失败,因为await
之后的逻辑可能会在一次性处置后执行。
【讨论】:
【参考方案2】:看起来 5.0.0 版将包括对带有监控的异步测试的支持。
此Issue 已提出,work completed 正在等待文档成为 updated 和版本 5.0.0 发布。
但目前有一个预发布版,代码更改5.0.0-beta2 可以从 NuGet 上的预发布版中获取
来自更改日志:
Breaking 将旧的线程不安全 MonitorEvents API 替换为新的 将返回线程安全监视的监视器扩展方法 暴露诸如 Should().Raise() 和元数据之类的方法的范围 OccurredEvents 和 MonitoredEvents
因此,更新后的 NuGet 代码将如下所示:
[TestInitialize]
public void TestSetup()
this.notifyCount = 0;
this.simpleNotify = new SimpleNotify();
this.simpleNotify.PropertyChanged += SimpleNotify_PropertyChanged;
Thread thread = new Thread(this.bumpCount)
IsBackground = true,
Name = @"My Background Thread",
Priority = ThreadPriority.Normal
;
thread.Start();
[TestMethod]
public async Task TestMethod1()
using (var MonitoredSimpleNotify = this.simpleNotify.Monitor())
await Task.Delay(100);
this.notifyCount.Should().Be(1);
MonitoredSimpleNotify.Should().RaisePropertyChangeFor(x => x.Count); // New API for Monitoring
【讨论】:
以上是关于Fluent-ASsertions ShouldRaisePropertyChangeFor 不适用于异步任务?的主要内容,如果未能解决你的问题,请参考以下文章