有没有办法检查单元测试中是否调用了EventWaitHandle的set方法?

时间:2011-04-14 13:31:31

标签: multithreading unit-testing mocking moq

我尝试过使用模拟框架(Moq),但它不起作用,因为Set是一个不可覆盖的方法。然后我愚蠢地尝试通过扩展类来创建自己的EventWaitHandle。似乎没有任何意义,我可以在任何代码中挂钩来检测set是否实际上被调用。

我想做一些类似于Timer.Dispose(WaitHandle notifyObject)的事情,其中​​有人可以传入一个等待句柄,当事情完成时我会调用它。

我更愿意这样做,而无需创建包装类。这似乎是双方的额外努力和工作,我和那些必须使用我的班级创建包装的人。

2 个答案:

答案 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;
        });
    }