I\'m developing an asp.net (classic) application trying to implement the MVP pattern using this example. In trying to unit test my presenter and using the following pattern,
It would appear that this functionality is not currently available in moq, but may appear in a future version (I had a look in the 4.0.812.4 beta, but it doesn't seem to be there).
It may be worth asking the question, "why does SomePresenter
need to subscribe to the View's Load
and Init
events?" Presumably it is because the SomePresenter
class needs to respond to those events. So it might be better to use the Raise
method on your Mock<IView>
to raise the Load
and Init
events, and then assert that SomePresenter
did the right thing in response to them.
I spent some time with this question and the solution which I'm using in my project is:
Unit test:
// Arrange
TestedObject.Setup(x => x.OnEvent1());
TestedObject.Setup(x => x.OnEvent2());
// Act
TestedObject.Object.SubscribeEvents();
TestedObject.Raise(x => x.Event1 += null);
TestedObject.Raise(x => x.Event2 += null);
// Assert
TestedObject.Verify(x => x.OnEvent1(), Times.Once());
TestedObject.Verify(x => x.OnEvent2(), Times.Once());
Tested method:
this.Event1 += OnEvent1;
this.Event2 += OnEvent2;
So, first you have to mock the methods which you will assign the events, after you call the method which you want to test, and finally raise all subscribed events. If the event is really subscribed, you can check with Moq if the assigned method is called.
GLHF!
The moq 4.13
introduced this feature. Now it is possible to verify if add\remove
has been invoked. Therefore four new methods have been introduced:
SetupAdd
SetupRemove
VerifyAdd
VerifyRemove
Example
var mock = new Mock<IAdder<EventArgs>>();
mock.SetupAdd(m => m.Added += (sender, args) => { });
mock.Object.Added += (sender, args) => { };
mock.Object.Added += (sender, args) => { };
mock.VerifyAdd(m => m.Added += It.IsAny<EventHandler>(), Times.Exactly(2));
NB: Notice that in order to verify at least one setup should be added. The reason is to keep backward compatibility with the older version of moq
.
I know it's maybe too late for #Dilip, but this answer can be helpful for those who are trying to do the same. Here is the test class
public delegate void SubscriptionHandler<T>(string name, T handler);
public class SomePresenterTest
{
[Test]
public void Subscription_Test()
{
var someServiceMock = new Mock<ISomeDomainService>();
var viewMock = new Mock<IView>();
//Setup your viewMock here
var someView = new FakeView(viewMock.Object);
EventHandler initHandler = null;
someView.Subscription += (n, h) => { if ((nameof(someView.Init)).Equals(n)) initHandler=h; };
Assert.IsNull(initHandler);
var presenter = new SomePresenter(someServiceMock.Object, someView);
Assert.IsNotNull(initHandler);
Assert.AreEqual("OnInit", initHandler.Method?.Name);
}
}
FakeView is a decorator implemented as follow (pay attention to Events:Init/Load{add;remove}):
public class FakeView : IView
{
public event SubscriptionHandler<EventHandler> Subscription;
public event SubscriptionHandler<EventHandler> Unsubscription;
private IView _view;
public FakeView(IView view)
{
Assert.IsNotNull(view);
_view = view;
}
public bool IsPostBack => _view.IsPostBack;
public bool IsValid => _view.IsValid;
public event EventHandler Init
{
add
{
Subscription?.Invoke(nameof(Init), value);
_view.Init += value;
}
remove
{
Unsubscription?.Invoke(nameof(Init), value);
_view.Init -= value;
}
}
public event EventHandler Load
{
add
{
Subscription?.Invoke(nameof(Load), value);
_view.Init += value;
}
remove
{
Unsubscription?.Invoke(nameof(Load), value);
_view.Init -= value;
}
}
public void DataBind()
{
_view.DataBind();
}
}