Thomas
Thomas

Reputation: 5911

Moq Interface with Action property

I am currently working with the framework Fleck and I want to mock the interface IWebSocketConnection. It has some property of type Action and I would like to raise theses events.

I tried so far without success to raise it as a events like this :

fleckInterfaceMock.Raise(mock => mock.OnClose += null);

Or even to call it directly like this :

fleckInterfaceMock.Object.OnClose();

I didn't found anything interesting on the official documentation

The interface :

namespace Fleck
{
    public interface IWebSocketConnection
    {
        IWebSocketConnectionInfo ConnectionInfo { get; }
        bool IsAvailable { get; }
        Action<byte[]> OnBinary { get; set; }
        Action OnClose { get; set; }
        Action<Exception> OnError { get; set; }
        Action<string> OnMessage { get; set; }
        Action OnOpen { get; set; }
        Action<byte[]> OnPing { get; set; }
        Action<byte[]> OnPong { get; set; }

        void Close();
        Task Send(byte[] message);
        Task Send(string message);
        Task SendPing(byte[] message);
        Task SendPong(byte[] message);
    }
}

Upvotes: 0

Views: 405

Answers (1)

Jeppe Stig Nielsen
Jeppe Stig Nielsen

Reputation: 61952

Note that OnClose and the other members in the interface are not actually events. They are really get-set properties whose property types just happen to be delegate types.

For that reason I do not think you can or shall use Raise from Moq.

If you want the invocation:

// desired use
fleckInterfaceMock.Object.OnClose();

to succeed, that requires the get accessor to return a non-null Action.

You could do it like this:

// possible Moq setup
Action a = () => { Console.WriteLine("Testing OnClose."); };
fleckInterfaceMock.Setup(x => x.OnClose).Returns(a);

If you want delegate combination (this is not true event subscription; we have no event) of the type:

// desired use
fleckInterfaceMock.Object.OnClose += someAction;

to succeed, the mock must first tolerate a get of the property, like before, and secondly it must tolerate that you set the property (it will be set to the "sum" of (1) what was returned by the get, and (2) someAction.

There are many ways you could achieve that. One way is simply:

// possible Moq setup
fleckInterfaceMock.SetupProperty(x => x.OnClose);

That will simply turn OnClose into a property which allows both get and set, and which remembers what it is set to and gives that value back when get is called.

Upvotes: 1

Related Questions