我有以下測試,支持類,但我無法弄清楚如何驗證依賴關係上的調用。Moq驗證與匿名類型參數
[TestFixture]
public class AnonymousGenericTypeParameterTests
{
[Test]
public void Test()
{
// Arrange
var dependency = new Mock<IDependency>();
var towns = new List<Town>
{
new Town { Name = "Lifford", County = "Donegal", Country="Ireland", Population = 1658 },
new Town { Name = "Ballyshannon", County = "Donegal", Country="Ireland", Population = 2504 },
new Town { Name = "Buxton", County = "Derbyshire", Country="United Kingdom", Population = 13599 },
};
var sut = new MyClass(dependency.Object);
// Act
sut.DoSomething(towns);
// Assert
// The following line needs to be fixed.
dependency.Verify(d => d.Execute(It.IsAny<IEnumerable<object>>(), It.IsAny<Func<object, decimal?>>()));
}
}
public interface IDependency
{
void Execute<T>(IEnumerable<T> collection, Func<T, decimal?> rateSelector);
}
public class MyClass
{
private readonly IDependency dependency;
public MyClass(IDependency dependency)
{
this.dependency = dependency;
}
public void DoSomething(IEnumerable<Town> towns)
{
var counties = towns.GroupBy(t => new {t.Country,t.County});
foreach (var county in counties)
{
dependency.Execute(county, c => c.Population);
}
}
}
public class Town
{
public string Name { get; set; }
public string County { get; set; }
public int Population { get; set; }
public string Country { get; set; }
}
根據起訂量的測試輸出時,進行調用是:
Dependency.Execute(System.Linq.Lookup`2+Grouping[<>f__AnonymousType0`2[System.String,System.String],UniFocus.Staffscope4.Tests.Town], System.Func`2[UniFocus.Staffscope4.Tests.Town,System.Nullable`1[System.Decimal]])
我看到很多的MOQ(如this和this和this)關於匿名參數的問題,但無法找到與使用匿名類型作爲實際類型參數有關的任何內容。
什麼可以放在驗證行,以便它實際上驗證內部的呼叫?
注:我的例子IDependency
沒有返回值(它已經足夠複雜,我認爲),但會有答案是implictly或明確處理Setup()
以及Verify()
獎勵榮譽。
更新 傑西的解決方案只通過測試,因爲我在製作示例時做出了不好的選擇。我應該已經意識到任何IGrouping<out TKey, out TElement>
也是IEnumerable<TElement>
。有更通用的解決方案嗎?
更新2 我覺得我原來的例子可能太精細了,並沒有很好地代表我的問題的實際標題。有沒有任何解決方案可以用於這個更簡單直觀的例子?
using Moq;
using NUnit.Framework;
namespace Tests
{
[TestFixture]
public class SimpleAnonymousGenericTypeParameterTests
{
[Test]
public void Test()
{
// Arrange
var dependency = new Mock<IDependency>();
var sut = new MyClass(dependency.Object);
// Act
sut.DoSomething("Donegal", "Lifford");
// Assert
// This verify works for both calls to Execute()
dependency.Verify(d => d.Execute(It.IsAny<object>()), Times.Exactly(2));
// This verify should specifically refer to only the first call to Execute()
dependency.Verify(d => d.Execute(It.IsAny</*HowToRepresentAnonymousTypeHere*/object>()), Times.Once);
}
public interface IDependency
{
void Execute<T>(T thing);
}
public class MyClass
{
private readonly IDependency dependency;
public MyClass(IDependency dependency)
{
this.dependency = dependency;
}
public void DoSomething(string county, string town)
{
dependency.Execute(new { county, town });
object someUnknownObject = "";
dependency.Execute(someUnknownObject);
}
}
}
}
正試圖弄清楚如何通過。Execute()如下所示:'dependency.Execute(county,c => c.Population);'。當我把鼠標放在那裏的'縣'上時,我發現它的類型是'IGrouping <'a,Town>',其中''a是新的{string Country,string County}'。那麼Moq如何看待'Execute()'通過了'IEnumerable'?那麼我想到,一個'IGrouping '也是'IEnumerable ':'public interface IGrouping :IEnumerable ,IEnumerable'。所以你的編輯只會通過,因爲我選擇了一個不好的類型(IGrouping)作爲示例: –
DoSomething將一個IEnumerable組分組以產生一個IEnumerable <分組>,然後DoSomething遍歷IEnumerable >並調用IDependency。在每個IGrouping 元素上執行。TKey看起來並不重要 - county.Key永遠不會被引用,所以匿名對象永遠不會用作分組鍵)。 IDependency.Execute 預計T將由調用者提供,在本例中將始終由DoSomething傳遞給Town。 DoSomething還有其他一些變體需要支持嗎? –
你給我的見解解決了上面的例子,並解決了我在生產代碼中遇到的原始問題,所以非常感謝!不過,我覺得這是對原始問題的解決辦法,因爲我的匿名類型('IGrouping <'a,Town>')實現了非任意類型('IEnumerable'),因此很容易驗證它。在我接受這個答案之前,你能否看看我對問題的第二次更新,我的例子似乎更準確地反映了問題的標題?我開始認爲Moq沒有辦法做到這一點。謝謝你的耐心! –