Как я могу поднять событие на поддельном BackgroundWorker? - PullRequest
1 голос
/ 22 сентября 2009

Я пытаюсь проверить, как мой класс реагирует на то, что происходит, когда BackgroundWorker запускает событие RunWorkerCompleted.

Я использую RhinoMocks (если есть другой подход, я тоже хочу попробовать его), и код выглядит следующим образом:

//arrange
var bw1 = MockRepository.GenerateStub<BackgroundWorker>();
Action work1 = () => Thread.Sleep(1);
WorkQueueProcess processInQueue = new WorkQueueProcess(bw1) { Work = work1 };
var tested = new WorkQueue() { processInQueue };

// act
bw1.Raise(
    bw => bw.RunWorkerCompleted += 
        null, 
        bw1, 
        new RunWorkerCompletedEventArgs(null, null, false)
);

// assert
Assert.AreEqual(false, tested.IsBusy);

Я получаю исключение, которое говорит:

Неверный звонок, последний звонок был использовался или не был сделан звонок (сделать уверен, что вы звоните виртуальный (C #) / переопределяемый (VB) метод).

Что я делаю не так? Это потому, что у BackgroundWorker нет виртуальных методов? Я думал, что смогу вызвать событие независимо, потому что событие вряд ли когда-либо будет виртуальным.

1 Ответ

1 голос
/ 22 сентября 2009

Только класс, который определяет событие, может вызвать это событие. Это просто, как работает система событий в .NET.

Метод Raise, предоставляемый RhinoMocks, предназначен для использования с интерфейсами, определяющими события. В этом случае любой класс, реализующий этот интерфейс, имеет свое собственное событие и, следовательно, может вызвать его. Это также справедливо для типов, генерируемых RhinoMocks во время выполнения.

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

BackgroundWorker имеет метод OnRunWorkerCompleted, который будет вызывать событие. Этот метод является виртуальным, поэтому, если вы можете заставить RhinoMocks вызывать этот защищенный метод, вы сможете вызвать событие.

Я использую Moq, который не может сделать это - я не могу вспомнить, есть ли у RhinoMocks возможность вызывать защищенных членов.

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

Однако в качестве заключительного замечания я настоятельно рекомендую вам не пытаться выполнять модульное тестирование многопоточного кода - на этом пути стоит только боль ...

...