-
-
Notifications
You must be signed in to change notification settings - Fork 840
Open
Labels
Description
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
Additional Info
n\a
GillesTourreau