开发者

Is there a way to check that a EventWaitHandle's set method was called in a unit test?

I have tried using a mocking framework (Moq) but it doesn't work because Set is a non-overridable method. I then stupidly tried to make my own EventWaitHandle by extending the class. It doesn't seem that there is any point that I ca开发者_运维问答n hook in any code to detect if set was in fact called.

I want to do something similar to Timer.Dispose(WaitHandle notifyObject) where someone can pass in a wait handle and I will call set on it when something completes.

I would prefer to do this without having to create a wrapper class. It just seems like so much extra effort and work on both sides, mine and the person that has to use my class to create a wrapper.


This is unfortunately not possible. However, you are doing it the right way - Mocking away multithreading aspects of the code allowing tests to run single threaded. Tests then verifies that the correct methods (Set in this case) are called.

I wish the .NET-framework was designed more with tests in mind allowing us to mock this type of method by letting the class implement a simple interface.

I've been in the same situation with this exact method and also some other ones that lack an interface. In the end I ended upp either A) writing a wrapper B) not writing a tests.


It's less than ideal, but an alternative approach is to create separate Tasks to test that a 'Set' call is made, one to do the real work, and one to block on a WaitHandle. Then the test becomes a case of waiting for both Tasks to complete (obviously adding in timeouts to prevent waiting forever!).

A very crude example could be as follows:

    [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;
        });
    }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜