我尝试过使用模拟框架(Moq),但它不起作用,因为Set是一个不可覆盖的方法。然后我愚蠢地尝试通过扩展类来创建自己的EventWaitHandle。似乎没有任何意义,我可以在任何代码中挂钩来检测set是否实际上被调用。
我想做一些类似于Timer.Dispose(WaitHandle notifyObject)的事情,其中有人可以传入一个等待句柄,当事情完成时我会调用它。
我更愿意这样做,而无需创建包装类。这似乎是双方的额外努力和工作,我和那些必须使用我的班级创建包装的人。
答案 0 :(得分:0)
遗憾的是,这是不可能的。但是,您正在以正确的方式进行操作 - 模拟代码的多线程方面,允许测试运行单线程。然后测试验证是否调用了正确的方法(在这种情况下为Set
)。
我希望.NET框架的设计更多,考虑到测试,允许我们通过让类实现一个简单的接口来模拟这种类型的方法。
我使用这种确切的方法和其他缺少接口的方法一直处于同样的情况。最后我结束了upp要么A)写一个包装B)而不是写一个测试。
答案 1 :(得分:0)
这不太理想,但另一种方法是创建单独的任务来测试“Set”调用,一个用于执行实际工作,一个用于阻止WaitHandle。然后测试成为等待两个任务完成的情况(显然添加超时以防止永远等待!)。
一个非常粗略的例子可能如下:
[Test]
public void Test_Blocking()
{
// Arrange
var ewh = new EventWaitHandle(false, EventResetMode.ManualReset);
System.Threading.Tasks.Task<int> blocker = BlockOn(ewh, 0);
// Act
System.Threading.Tasks.Task worker = Work(ewh);
var allTasks = new[] { worker, blocker };
while (!allTasks.All(t => t.IsCompleted))
{
// spin
}
// Assert
Assert.That(blocker.Result, Is.EqualTo(1));
}
private static System.Threading.Tasks.Task<int> BlockOn(EventWaitHandle waitHandle, int counter)
{
return System.Threading.Tasks.Task.Factory.StartNew<int>(() =>
{
waitHandle.WaitOne();
return counter + 1;
});
}