Как проверить, приводит ли возникновение события к методу, вызываемому в зависимости от значения параметров?

Я пытаюсь написать модульный тест, который вызовет событие для фиктивного объекта, с которым связан мой тестовый класс.

Однако я хочу проверить, что, когда мой тестовый класс вызывает свой обработчик событий, он должен вызывать метод только для определенных значений параметров обработчика событий.

Кажется, мой тест пройден, даже если я прокомментирую код, который вызывает 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 ответ

Решение

Обычно я разбиваю подобные вещи как минимум на два теста. Первый проверяет, что запуск события вызывает соответствующий обратный вызов (и этот обратный вызов вызывается ВСЕГДА, никаких условий). Условная логика, которую вы пытались проверить, переходит в соответствующий обратный вызов, который проверяется дополнительными отдельными тестами.

Первый тест может быть реализован путем создания производного класса из тестируемого класса с соответствующим переопределением обратного вызова, чтобы просто записать, что он был успешно вызван. Затем, когда вы запускаете событие, вы можете убедиться, что обратный вызов вызван.

Следующим шагом является непосредственное тестирование метода обратного вызова, как и любого другого метода.

Вот скелетный тест с кодом проверки, который вам понадобится для первого теста. Обратите внимание, что 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 напрямую.

Другие вопросы по тегам