C#和Moq - 如何断言事件没有被提升

时间:2012-09-15 14:57:46

标签: c# unit-testing events moq

我有一个应用程序根据Sim对象的状态引发事件。特别是,如果Sim的状态发生变化 - 即从PinRequired变为Accessible - 将引发OnStatus事件。事件在新线程上通知侦听器。

我在单元测试中使用Moq,并且能够断言OnStatus是这样引发的:

        [Test]
    public void TestOnStatusIsRaised()
    {
        Sim sim = new Sim();

        sim.OnStatus += OnStatus;

        lock (this)
        {
            sim.UpdateSimInfo(new Info("a new status"));
            Monitor.Wait(this);
        }

        Assert.IsTrue(_onStatusCalled);
    }

    private void OnStatus(SimStatus obj)
    {
        lock (this)
        {
            _onStatusCalled = true;
            Monitor.Pulse(this);
        }
    }

正如您所看到的,使用Monitor类我可以等到事件被引发,然后继续并断言_onStatusCalled标志已设置为true。

当我想断言事件没有被提出时,我的困难就出现了。我不能使用Monitor来等待事件不被提出,因为测试会永远等待!我可以在等待中添加超时,但这似乎是一个肮脏的黑客。

我尝试了以下内容:

        [Test]
    public void TestOnStatusIsNotFired()
    {
        Sim sim = new Sim();
        sim.OnStatus += onStatus => Assert.Fail("OnStatus Was called");

        sim.UpdateSimInfo(new Info("the same status"));
    }

但它不起作用 - 在修复代码以确保不引发事件之前,测试总是通过。我甚至已经逐步完成了代码并观察到Assert.Fail()抛出异常,但是这不会导致测试失败,因为我的事件在try / catch块中引发并且捕获了NUnit异常。

有什么想法吗?

3 个答案:

答案 0 :(得分:5)

简而言之,单元测试多线程代码。您将其拆分为单线程部分并分别测试每个部分。

答案 1 :(得分:0)

如果您还有NoStatus的活动,该怎么办?

[Test]
public void TestOnStatusIsNotFired()
{
    Sim sim = new Sim();
    var mre = new ManualResetEvent(false);
    sim.OnStatus += onStatus => { mre.Set(); Assert.Fail("OnStatus Was called");}
    sim.NoStatus += () => { mre.Set();}

    sim.UpdateSimInfo(new Info("the same status"));
    mre.WaitOne()
}

答案 2 :(得分:0)

如何使用以下内容:

mock.Verify(foo => foo.Execute("ping"), Times.Never());

您还可以验证是否已使用以下命令调用OnStatus:

mock.Verify(foo => foo.Execute("ping"), Times.AtLeastOnce());

尝试此链接以获取大量优质短片:http://code.google.com/p/moq/wiki/QuickStart