Как поднять событие при вызове метода с помощью Moq?
У меня есть такой интерфейс:
public interface IMyInterface
{
event EventHandler<bool> Triggered;
void Trigger();
}
И у меня есть обманный объект в моем unit test, как это:
private Mock<IMyInterface> _mockedObject = new Mock<IMyInterface>();
Я хочу сделать что-то вроде этого:
// pseudo-code
_mockedObject.Setup(i => i.Trigger()).Raise(i => i.Triggered += null, this, true);
Однако это не похоже на то, что Raise
доступен в интерфейсе ISetup
, который возвращается. Как это сделать?
Ответы
Ответ 1
Ваш псевдокод был почти точным. Вам нужно использовать Raises
вместо Raise
. Проверьте Moq Quickstart: События для версий Moq 4.x, и вы увидите, где вы допустили ошибку.
_mockedObject.Setup(i => i.Trigger()).Raises(i => i.Triggered += null, this, true);
Вот фрагмент формы 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);
Ответ 2
Итак, я понял, что я делаю неправильно. Я собираюсь опубликовать здесь ответ, но даю кредит Нкоси, потому что я действительно не задал вопрос правильно, и он предоставил много полезной информации.
С помощью метода async для макета вам нужно сначала указать, что он возвращает задачу, прежде чем вы сможете инициировать события. Поэтому в моем примере (понимая, что в качестве сигнатуры метода я должен был иметь Task Trigger();
, это код, который я искал:
_mockedObject.Setup(i => i.Trigger())
.Returns(Task.FromResult(default(object)))
.Raise(i => i.Triggered += null, this, true);
По-видимому, это может быть еще более упрощено в С# 4.6, а именно:
_mockedObject.Setup(i => i.Trigger())
.Returns(Task.CompletedTask)
.Raise(i => i.Triggered += null, this, true);
Ответ 3
Расширяясь в ответе SoaperGEM, все методы, возвращающие что-то (независимо от типа), должны иметь это возвращаемое значение, указанное перед запуском события. Поскольку async методы возвращают Task
, методы async попадают в эту категорию. У меня есть метод, который возвращает string
, и я пытался выяснить, почему я не мог инициировать событие с помощью объекта Mock. Затем я попытался вернуться первым, и все получилось просто.
Взяв пример SoaperGEM и предположив, что Trigger()
возвращает строку:
_mockedObject.Setup(i => i.Trigger())
.Returns("somestring")
.Raises(i => i.Triggered += null, this, true);