Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Mock setup order can lead to unexpected object cast exceptions during runtime #1650

@payn-git

Description

@payn-git

Describe the Bug

When generic method is setup. It depends on the order of setup if execution will succeed during runtime. Order of setup should not impact execution.

Setup mock this way will lead to cast exception during runtime
layoutAc.Setup(x => x.GetActiveViews<IVolumeView>()).Returns(segmentViews.OfType<IVolumeView>());
layoutAc.Setup(x => x.GetActiveViews<ISegmentView>()).Returns(segmentViews);

Same setup but swapped order will pass during execution
layoutAc.Setup(x => x.GetActiveViews<ISegmentView>()).Returns(segmentViews);
layoutAc.Setup(x => x.GetActiveViews<IVolumeView>()).Returns(segmentViews.OfType<IVolumeView>());

Steps to Reproduce

See attached reproducible project

internal class Tests
{
    private class TestClass
    {
        internal static void ExecuteSegmentVolume(ILayoutManagementAC mylm)
        {
            var t = mylm.GetActiveViews<ISegmentView>();
            var t1 = mylm.GetActiveViews<IVolumeView>();
        }

        internal static void ExecuteVolumeSegment(ILayoutManagementAC mylm)
        {
            var t1 = mylm.GetActiveViews<IVolumeView>();
            var t = mylm.GetActiveViews<ISegmentView>();
        }
    }

    [Test]
    public void SetupVolumeSegmentExecuteSegmentVolume()
    {
        var layoutAc = new Mock<ILayoutManagementAC>();
        var segmentView = new Mock<ISegmentView>();
        segmentView.As<IVolumeView>();
        var segmentViews = new List<ISegmentView>() { segmentView.Object };

        layoutAc.Setup(x => x.GetActiveViews<IVolumeView>()).Returns(segmentViews.OfType<IVolumeView>());
        layoutAc.Setup(x => x.GetActiveViews<ISegmentView>()).Returns(segmentViews);

        TestClass.ExecuteSegmentVolume(layoutAc.Object);
    }

    [Test]
    public void SetupVolumeSegmentExecuteVolumeSegment()
    {
        var layoutAc = new Mock<ILayoutManagementAC>();
        var segmentView = new Mock<ISegmentView>();
        segmentView.As<IVolumeView>();
        var segmentViews = new List<ISegmentView>() { segmentView.Object };

        layoutAc.Setup(x => x.GetActiveViews<IVolumeView>()).Returns(segmentViews.OfType<IVolumeView>());
        layoutAc.Setup(x => x.GetActiveViews<ISegmentView>()).Returns(segmentViews);

        TestClass.ExecuteVolumeSegment(layoutAc.Object);
    }

    [Test]
    public void SetupSegmentVolumeExecuteSegmentVolume()
    {
        var layoutAc = new Mock<ILayoutManagementAC>();
        var segmentView = new Mock<ISegmentView>();
        segmentView.As<IVolumeView>();
        var segmentViews = new List<ISegmentView>() { segmentView.Object };

        layoutAc.Setup(x => x.GetActiveViews<ISegmentView>()).Returns(segmentViews);
        layoutAc.Setup(x => x.GetActiveViews<IVolumeView>()).Returns(segmentViews.OfType<IVolumeView>());

        TestClass.ExecuteSegmentVolume(layoutAc.Object);
    }

    [Test]
    public void SetupSegmentVolumeExecuteVolumeSegment()
    {
        var layoutAc = new Mock<ILayoutManagementAC>();
        var segmentView = new Mock<ISegmentView>();
        segmentView.As<IVolumeView>();
        var segmentViews = new List<ISegmentView>() { segmentView.Object };

        layoutAc.Setup(x => x.GetActiveViews<ISegmentView>()).Returns(segmentViews);
        layoutAc.Setup(x => x.GetActiveViews<IVolumeView>()).Returns(segmentViews.OfType<IVolumeView>());

        TestClass.ExecuteVolumeSegment(layoutAc.Object);
    }
}

public interface ISegmentView
{
}

public interface IVolumeView : ISegmentView
{
}

public interface ILayoutManagementAC
{
    IEnumerable<T> GetActiveViews<T>() where T : ISegmentView;
}

Expected Behavior

Execution should pass regardless of Mock setup order

Exception with Stack Trace

System.InvalidCastException : Unable to cast object of type 'System.Collections.Generic.List`1[MoqBug.ISegmentView]' to type 'System.Collections.Generic.IEnumerable`1[MoqBug.IVolumeView]'.
   at Castle.Proxies.ILayoutManagementACProxy.GetActiveViews[T]()
   at MoqBug.Tests.TestClass.ExecuteSegmentVolume(ILayoutManagementAC mylm) in E:\Devloping\MoqBug\Tests.cs:line 21
   at MoqBug.Tests.SetupVolumeSegmentExecuteSegmentVolume() in E:\Devloping\MoqBug\Tests.cs:line 42

Version Info

Moq 4.20.70
NUnit 4.4.0

MoqBug.zip

Additional Info

n\a

Back this issue
Back this issue

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions