![](/img/trans.png)
[英]Setup Mock for generic function with generic Lambda using Moq It.IsAny
[英]Mock behavior loose for single method or generic It.IsAny
我有一個抽象類Shape
和幾個繼承自它的類( Square
、 Rectangle
、 Triangle
、 Circle
,...)。 我還有一個AreaCalculator
類,其中包含一個名為CalculateAreasByShape()
的方法。 此方法為每個Shape
類型調用一系列CalculateShapeAreas<TShape>(List<TShape> shapes)
方法。
現在,在我的單元測試中,我有以下代碼:
...
var areaMock = new Mock<AreaCalculator>(MockBehavior.Strict);
areaMock.Setup(m => m.CalculateAreasByShape()).Returns(new Dictionary<Type, decimal>());
var canvas = new DemoCanvas(shapes, perimeterMock.Object, areaMock.object);
var result = canvas.RunShapeCalculations();
...
這段代碼失敗了,因為MockBehavior
設置為Strict
並且沒有設置CalculateShapeAreas<TShape>()
方法。 現在,我知道我可以為每個 Shape 類型運行一個設置,例如:
areaMock.Setup(m => m.CalculateShapeAreas<Triangle>(It.IsAny<List<Triangle>>())).Returns(default(decimal));
但這會產生很多重復的代碼。 我想知道我們是否可以使用所有形狀都繼承自同一個基類的事實。 我嘗試了以下方法,但不起作用:
areaMock.Setup(m => m.CalculateShapeAreas<Shape>(It.IsAny<List<Shape>>())).Returns(default(decimal));
或者,是否可以在單個泛型方法上設置MockBehavior.Loose
(也就是說,它不會檢查實際類型)?
It.IsAny
開放的通用支持尚不存在於moq
(版本4.12.0)。 最終有一些計划介紹這個,看看這里
我認為您面臨的問題是因為您使用List<T>
作為輸入參數。 您可能會注意到List<T>
不是協變的。
那是什么意思?
List<Shape> shapeList;
IEnumerable<Shape> shapeEnumerable;
var triag = new List<Triangle>();
shapeList = triag; // NOT ALLOWED
shapeEnumerable = triag; // ALLOWED
嘲笑時同樣會產生問題。 一種解決方案可能是更改interface
,而不是傳遞List<T>
傳遞IEnumerable<out T>
,或者正如@JeppeStigNielsen 指出的那樣IReadOnlyList<out T>
。 實際上,可以使用由List<T>
實現的T
接口中的任何協變。
areaMock
.Setup(m => m.CalculateShapeAreas<Shape>(It.IsAny<IEnumerable<Shape>>()))
.Returns(default(decimal));
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.