Search code examples
c#unit-testingeventsmockingmoq

Raise event of mocking object and passing there as argument object used for calling method


I have an interface IPeakCommunication, and derived class PeakCommunication. Inside derived class I have an implementation of method Send(RequestData request) which do something, and as I expect invokes event RequestReceived and passing there argument request.

I would to create unit tests for some classes which interact with IPeakCommunication, and call Send(RequestData request) method. But I have no idea how to create a Mock which takes an object from arguments and use it for invoking RequestReceived event.

public interface IPeakCommunication : IDisposable
{
#region Delegates
delegate void PeakRequestReceivedHandler(RequestData data);
#endregion

#region Events
event PeakRequestReceivedHandler? RequestReceived;
#endregion

#region Methods
void Send(RequestData data);
#endregion
}

The code which I tried to make:

var mockCommunication = new Mock<IPeakCommunication>();
mockCommunication.Setup(x => x.Send(It.IsAny<RequestData>()))
    .Raises(x => x.RequestReceived += null, new object[] { /*argument from Send()?*/ } );

Solution

  • You can use Callback:

    var mockCommunication = new Mock<IPeakCommunication>();
    
    // Setup with callback which uses Raise
    mockCommunication.Setup(x => x.Send(It.IsAny<RequestData>()))
        .Callback((RequestData rd) => 
            mockCommunication.Raise(c => c.RequestReceived += null, rd));
    
    // Act
    var obj = mockCommunication.Object;
    // sample subscriber:
    obj.RequestReceived += rd => Console.WriteLine(rd.Data);
    obj.Send(new RequestData { Data = 42 }); // Prints 42
    
    // sample data object
    public class RequestData
    {
        public int Data { get; set; }
    }
    

    Demo @dotnetfiddle.net