Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Moq raise event error - Parameter count mismatch

Background

I have the following scenario:

  • MailItemProxy class with a constructor with a single argument of type MailItem (MailItem is actually part of the Microsoft.Office.Interop.Outlook namespace)
  • Within the constructor of MailItemProxy, an event called PropertyChange (from the Outlook MailItem class) is registered:
public MailItemProxy(MailItem mailItem)
{
    this.mailItem = mailItem;
    this.mailItem.PropertyChange += this.MailItem_PropertyChange;
}

My MailItemProxy class implements INotifyPropertyChanged so has its own PropertyChanged event (notice this is "PropertyChanged" rather than the Outlook MailItem's own "PropertyChange" tense).

The *MailItem_PropertyChange* event handler is as follows:

 private void MailItem_PropertyChange(string name)
 {
     if (this.PropertyChanged != null)
     {
         this.PropertyChanged(this, new PropertyChangedEventArgs(name));
     }
 }

Intention

My intention here is to test when the MailItem PropertyChange event is fired, the class under test (MailItemProxy) has subscribed to that event correctly.

The test framework I am using is Moq.

The issue I am getting is I receive a runtime error "Parameter count mismatch" on my Act line where I attempt to raise a PropertyChange event for the mailItemStub. The PropertyChange event does just take in one parameter of type string as defined by delegate ItemEvents_10_PropertyChangeEventHandler(string Name) within the Microsoft.Office.Interop.Outlook namespace. If I remove the last two Arrange lines for mailItemProxy, the Act line then runs fine for some reason but I obviously need the proxy as this is the class I am testing.

Any ideas why I am receiving this error?

 [TestMethod]
 public void PropertyChanged_WhenMailItemPropertyChange_EventIsCalled()
 {
     // Arrange
     bool eventDispatched = false;
     var mailItemStub = new Mock<MailItem>();
     var mailItemProxy = new MailItemProxy(mailItemStub.Object);
     mailItemProxy.PropertyChanged += (sender, args) => { eventDispatched = true; };

     // Act
     mailItemStub.Raise(x => x.PropertyChange += (name) => { });

     // Assert
     Assert.IsTrue(eventDispatched);
 }

Stack Trace

Test Name:  PropertyChanged_WhenMailItemPropertyChange_EventIsCalled
Test Outcome:   Failed
Test Duration:  0:00:00.2764026

Result Message: 
Test method UI.Office.UnitTests.MailItemProxyTest.PropertyChanged_WhenMailItemPropertyChange_EventIsCalled threw exception: 
System.Reflection.TargetParameterCountException: Parameter count mismatch.
Result StackTrace:  
at Moq.Mock`1.Raise(Action`1 eventExpression, Object[] args)
   at UI.Office.UnitTests.MailItemProxyTest.PropertyChanged_WhenMailItemPropertyChange_EventIsCalled()
like image 248
Casey Avatar asked Feb 11 '14 15:02

Casey


2 Answers

There are two overloads of Mock.Raise - you will either need to pass an EventArgs, or a params object[] as the second args parameter. In your case, you can use the latter and pass the string name of the property changed:

e.g.

 mailItemStub.Raise(x => x.PropertyChange += (name) => { }, "FooBar");

More here

like image 152
StuartLC Avatar answered Sep 18 '22 00:09

StuartLC


Update from someone who had a related issue

I also had the issue that I couldn't really get the parameters right when raising an event, in my case with one (relevant) parameter.

This is the event that I want to reach within my production code.

private void ProcessDataSet(object sender, IMeasurementDataSet e)
{
    ...
}

I finally found two equivalent syntax for achieving this (it seems like the two separate parameters this and measurementDataSet.Object are converted into a object[] anyway):

_dataRecorder.Raise(mock => mock.DataSetAvailable += null, new object[] {this, measurementDataSet.Object });
_dataRecorder.Raise(mock => mock.DataSetAvailable += null, this, measurementDataSet.Object);

Once more I will also reference Moq's excellent Quickstart Guide - it really helps!

like image 43
Dani Neuss Avatar answered Sep 20 '22 00:09

Dani Neuss