Creating a complex event using Moq in C #

The following code should be self-esteem: we have an adapter that uses events from a transport (layer) that contains a MessageRegistrar (the type of an object, because we cannot say its type, and mainly because it is an outdated code :-)). The transport layer has concrete that has an event. I want to check the case when the event is fired, so ..

After several hours of trying to understand why this will not work, I propose the following task:

[TestFixture]
public class AdaptorTests
{
    public delegate void TracksEventHandler(object sender, List<int> trklst);

    public class MyEventHolder
    {
        public virtual event TracksEventHandler EventName;
    }

    public interface ITransport
    {
        object MessageRegistrar { get; }
    }

    public class MyTransport : ITransport
    {
        private readonly MyEventHolder m_eventHolder;

        public MyTransport(MyEventHolder eventHolder)
        {
            m_eventHolder = eventHolder;
        }

        public virtual object MessageRegistrar
        {
            get { return m_eventHolder; }
        }
    }

    public class MyAdaptor
    {
        private readonly ITransport m_transport;

        public MyAdaptor(ITransport transport)
        {
            EventTriggered = false;
            m_transport = transport;
        }

        public void Connect()
        {
            MyEventHolder eventHolder = m_transport.MessageRegistrar as MyEventHolder;
            if (eventHolder != null)
                eventHolder.EventName += EventHolderOnEventName;
        }

        private void EventHolderOnEventName(object sender, List<int> trklst)
        {
            EventTriggered = true;
        }

        public bool EventTriggered { get; private set; }
    }

    [Test]
    public void test1()
    {
        Mock<MyEventHolder> eventHolderMock = new Mock<MyEventHolder> {CallBase = true};

        Mock<MyTransport> transportMock = new Mock<MyTransport>(eventHolderMock.Object) {CallBase = true};

        MyAdaptor adaptor = new MyAdaptor(transportMock.Object);
        adaptor.Connect();

        MyEventHolder eventHolder = transportMock.Object.MessageRegistrar as MyEventHolder;
        Mock.Get(eventHolder).Raise(eh => eh.EventName += null, new List<int>());

        Assert.IsTrue(adaptor.EventTriggered);
    }

    [Test]
    public void test2()
    {
        Mock<MyEventHolder> eventHolderMock = new Mock<MyEventHolder> { CallBase = true };

        Mock<MyTransport> transportMock = new Mock<MyTransport>(eventHolderMock.Object) { CallBase = true };

        MyAdaptor adaptor = new MyAdaptor(transportMock.Object);
        adaptor.Connect();

        MyEventHolder eventHolder = transportMock.Object.MessageRegistrar as MyEventHolder;
        Mock.Get(eventHolder).Raise(eh => eh.EventName += null, null, new List<int>());

        Assert.IsTrue(adaptor.EventTriggered);
    }

}

My question is: why does the test fail (at least one of them)?

EDIT @ 151217-0822 Added 'adapter.Connect ()' to the original message (still will not fix the problem).

Temporary solution

Credits for @Patrick Quirk: Thanks!

, : , , -, , : "eventHolder.FireEventNameForTestings( ());":

    public class MyEventHolder
    {
        public virtual event TracksEventHandler EventName;

        public virtual void FireEventNameForTestings(List<int> trklst)
        {
            TracksEventHandler handler = EventName;
            if (handler != null)
                handler(this, trklst);
        }
    }

    [Test]
    public void test3()
    {
        Mock<MyEventHolder> eventHolderMock = new Mock<MyEventHolder> { CallBase = true };

        Mock<MyTransport> transportMock = new Mock<MyTransport>(eventHolderMock.Object) { CallBase = true };

        MyAdaptor adaptor = new MyAdaptor(transportMock.Object);
        adaptor.Connect();

        MyEventHolder eventHolder = transportMock.Object.MessageRegistrar as MyEventHolder;
        eventHolder.FireEventNameForTestings(new List<int>());

        Assert.IsTrue(adaptor.EventTriggered);
    }

..

+4
1

, CallBase Raise() ( ) .

, Moq:

if (invocation.Method.IsEventAttach())
{
    var delegateInstance = (Delegate)invocation.Arguments[0];
    // TODO: validate we can get the event?
    var eventInfo = this.GetEventFromName(invocation.Method.Name.Substring(4));

    if (ctx.Mock.CallBase && !eventInfo.DeclaringType.IsInterface)
    {
        invocation.InvokeBase();
    }
    else if (delegateInstance != null)
    {
        ctx.AddEventHandler(eventInfo, (Delegate)invocation.Arguments[0]);
    }

    return InterceptionAction.Stop;
}

, CallBase - true, ( invocation.InvokeBase()). CallBase - false, ( AddEventHandler). Raise(), Expression, DoRaise():

internal void DoRaise(EventInfo ev, EventArgs args)
{
    // ... parameter validation

    foreach (var del in this.Interceptor.InterceptionContext.GetInvocationList(ev).ToArray())
    {
        del.InvokePreserveStack(this.Object, args);
    }
}

. GetInvocationList()? , . .

, , , CallBase true.

, , CallBase true, - MyEventHolder, . , , , , , , , , .

+3

Source: https://habr.com/ru/post/1620392/


All Articles