如何测试引发事件是否会导致方法被调用以参数值为条件

时间:2010-03-29 17:06:50

标签: events tdd nunit rhino-mocks

我正在尝试编写一个单元测试,它将在我的测试类绑定的模拟对象上引发一个事件。

我热衷于测试的是,当我的测试类调用其事件处理程序时,它应该只调用eventhandler参数的某些值的方法。

即使我评论调用ProcessPriceUpdate(price)的代码,我的测试似乎也没有通过;

我在VS2005,所以请不要发脾气:(

因此...

public delegate void PriceUpdateEventHandler(decimal price);

public interface IPriceInterface{
    event PriceUpdateEventHandler PriceUpdate;
}

public class TestClass
{
    IPriceInterface priceInterface = null;

    TestClass(IPriceInterface priceInterface)
    {
        this.priceInterface = priceInterface;
    }

    public void Init()
    {
        priceInterface.PriceUpdate += OnPriceUpdate;
    }

    public void OnPriceUpdate(decimal price)
    {
        if(price > 0)
           ProcessPriceUpdate(price);
        }

    public void ProcessPriceUpdate(decimal price)
    {
        //do something with price
    }
}

到目前为止我的测试......:s

public void PriceUpdateEvent()
    {
        MockRepository mock = new MockRepository();
        IPriceInterface pi = mock.DynamicMock<IPriceInterface>();
        TestClass test = new TestClass(pi);

        decimal prc = 1M;

        IEventRaiser raiser;

        using (mock.Record())
        {
            pi.PriceUpdate += null;

            raiser = LastCall.IgnoreArguments().GetEventRaiser();

            Expect.Call(delegate { test.ProcessPriceUpdate(prc); }).Repeat.Once();

        }
        using (mock.Playback())
        {
            test.Init();
            raiser.Raise(prc);
        }
    }

1 个答案:

答案 0 :(得分:0)

我通常会将这种事情分解为至少两次测试。第一个验证触发事件调用适当的回调(并且该回调总是被调用,没有条件)。您尝试测试的条件逻辑,进入适当的回调,并通过其他单独的测试进行测试。

第一个测试可以通过从被测试的类创建派生类来实现,并使用适当的回调覆盖来简单地记录它被成功调用。然后,当您触发事件时,您可以验证是否已调用回调。

下一步是直接测试回调方法,就像使用任何其他方法一样。

这是一个骨架测试,带有第一次测试所需的验证码。请注意,OnPriceUpdate将在TestClass中变为虚拟:

public class TestClass_verifiesCallback : TestClass
{
    public bool WasCallbackCalled = false;
    public decimal PricePassedToCallback = 0;

    public override void OnPriceUpdate(decimal price)
    {
        WasCallbackCalled = true;
        pricePassedToCallback = price;
    }
}

... test methods

public TestInitSetsPriceUpdateCallback()
{
   .. setup

   var sut = new TestClass_verifiesCallback()

   .. run test

   // verification:
   Assert.IsTrue(sut.WasCallbackCalled);
   Assert.AreEqual(expectedValue, sut.PricePassedToCallback);
}

您以后的测试可以直接测试OnPriceUpdate。