Недавно я написал серию постов в блоге о юнит-тестировании последовательностей событий для объектов, которые публикуют синхронные и асинхронные события. Посты описывают подход и структуру модульного тестирования и предоставляют полный исходный код с тестами.
Я описываю реализацию «монитора событий», который позволяет писать модульные тесты последовательности событий более аккуратно, т. Е. Избавиться от всего грязного стандартного кода.
Используя монитор событий, описанный в моей статье, тесты можно записать так:
var publisher = new AsyncEventPublisher();
Action test = () =>
{
publisher.RaiseA();
publisher.RaiseB();
publisher.RaiseC();
};
var expectedSequence = new[] { "EventA", "EventB", "EventC" };
EventMonitor.Assert(publisher, test, expectedSequence);
Или для типа, который реализует INotifyPropertyChanged:
var publisher = new PropertyChangedEventPublisher();
Action test = () =>
{
publisher.X = 1;
publisher.Y = 2;
};
var expectedSequence = new[] { "X", "Y" };
EventMonitor.Assert(publisher, test, expectedSequence);
А для случая в оригинальном вопросе:
MyClass myObject = new MyClass();
EventMonitor.Assert(myObject, () => { myObject.Width = 42; }, "Width");
EventMonitor выполняет всю тяжелую работу и запускает тест (действие) и утверждает, что события генерируются в ожидаемой последовательности (Ожидаемая последовательность). Он также выводит на экран хорошие диагностические сообщения о сбое теста. Reflection и IL используются под капотом, чтобы заставить работать динамическую подписку на события, но все это хорошо инкапсулировано, поэтому для написания тестов событий требуется только код, подобный приведенному выше.
В постах много подробностей, описывающих проблемы и подходы, а также исходный код:
http://gojisoft.com/blog/2010/04/22/event-sequence-unit-testing-part-1/