开发者

How to test if raising an event results in a method being called conditional on value of parameters

I'm trying to write a unit test that will raise an event on a mock object which my test class is bound to.

What I'm keen to test though is that when my test class gets its eventhandler called, it should only call a method on certain values of the eventhandler's parameters.

My test seems to pass even if I comment the code that calls ProcessPriceUpdate(price);

I'm in VS2005 so no lambdas please :(

So...

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
    }
}

And my test so far... :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);
        }
    }


I will usually break this kind of thing into at least two tests. The first verifies that triggering the event calls the appropriate callback (and that callback is ALWAYS called, no conditions). The conditional logic you were trying to test, that goes into the appropriate callback, which is tested by additional separate tests.

The first test can be implemented by creating a derived class from the class under test, with the appropriate callback overriden to simply record that it was called successfully. Then when you trigger the event, you can verify the callback is called.

Next step is to test the callback method directly, as you would any other method.

Here's a skeleton test with the validation code you'd need for the first test. Note that OnPriceUpdate would be made virtual in 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);
}

Your later tests can test OnPriceUpdate directly.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜