2016-05-17 4 views
11

У меня есть интерфейс, как это:Как поднять событие при вызове метода с помощью Moq?

public interface IMyInterface 
{ 
    event EventHandler<bool> Triggered; 
    void Trigger(); 
} 

И у меня высмеивали объект в моем модульном тестировании, как это:

private Mock<IMyInterface> _mockedObject = new Mock<IMyInterface>(); 

Я хочу сделать что-то вроде этого:

// pseudo-code 
_mockedObject.Setup(i => i.Trigger()).Raise(i => i.Triggered += null, this, true); 

Однако это не похоже, что Raise доступен на интерфейсе ISetup, который возвращается. Как мне это сделать?

ответ

14

Ваш Псевдокод был почти пятно на. Вам нужно было использовать Raises вместо Raise. Проверьте версии Moq Quickstart: Events на версии Moq 4.x, и вы увидите, где совершили ошибку.

_mockedObject.Setup(i => i.Trigger()).Raises(i => i.Triggered += null, this, true); 

Вот snippet form GitHub

// Raising an event on the mock 
mock.Raise(m => m.FooEvent += null, new FooEventArgs(fooValue)); 

// Raising an event on a descendant down the hierarchy 
mock.Raise(m => m.Child.First.FooEvent += null, new FooEventArgs(fooValue)); 

// Causing an event to raise automatically when Submit is invoked 
mock.Setup(foo => foo.Submit()).Raises(f => f.Sent += null, EventArgs.Empty); 
// The raised event would trigger behavior on the object under test, which 
// you would make assertions about later (how its state changed as a consequence, typically) 

// Raising a custom event which does not adhere to the EventHandler pattern 
public delegate void MyEventHandler(int i, bool b); 
public interface IFoo 
{ 
    event MyEventHandler MyEvent; 
} 

var mock = new Mock<IFoo>(); 
... 
// Raise passing the custom arguments expected by the event delegate 
mock.Raise(foo => foo.MyEvent += null, 25, true); 
+0

Это письмо-для-письма именно то, что я имею в псевдокоде часть моего вопроса. Я спрашивал, потому что это недопустимый синтаксис; Вызов недоступен при вызове программы установки. – SoaperGEM

+0

Да, это так. Какую версию Moq вы используете? Я тестировал его в своем коде, и он там. Ты просто сделал опечатку. Проверьте ссылку, которую я включил. – Nkosi

+0

'Raise' делается на макет сам не настройки – Nkosi

4

Так я понял, что я делаю неправильно. Я собираюсь опубликовать ответ здесь, но отдать должное Нкоси, потому что я действительно не задал вопрос правильно, и он предоставил много полезной информации.

С помощью метода async на макет вам нужно сначала указать, что он возвращает задачу, прежде чем вы сможете запустить ее. Так что в моем примере (понимая, что я должен был Task Trigger(); как метод подписи, это код, который я искал:

_mockedObject.Setup(i => i.Trigger()) 
    .Returns(Task.FromResult(default(object))) 
    .Raise(i => i.Triggered += null, this, true); 

Видимо, это можно упростить еще дальше в C# 4.6, это:

_mockedObject.Setup(i => i.Trigger()) 
    .Returns(Task.CompletedTask) 
    .Raise(i => i.Triggered += null, this, true); 
1

Расширяясь на ответе SoaperGEM, все методы, возвращающие что-то (независимо от типа), должны иметь это возвращаемое значение, указанное перед запуском события. Так как методы async возвращают Task, методы async попадают в эту категорию. У меня есть метод, который возвращает a string, и я пытался выяснить, почему я не мог инициировать событие с помощью объекта Mock. Затем я попытался вернуться первым, и все прошло отлично.

Принимая пример SoaperGEM, и при условии, Trigger() возвращает строку:

_mockedObject.Setup(i => i.Trigger()) 
    .Returns("somestring") 
    .Raises(i => i.Triggered += null, this, true); 
Смежные вопросы