現在的短外賣該解決方案已被發現:凍結模擬就好AutoFixture/AutoMoq忽略注入實例/冷凍模擬
AutoFixture的回報;我的這個AutoFixture也產生了一個公共屬性,它有一個對測試非常重要的本地默認屬性,並且AutoFixture設置了一個新的值。除了Mark的答案之外,還有很多東西需要學習。
原題:
我開始嘗試AutoFixture昨天有起訂量遍他們我xUnit.net測試。我希望能夠替換Moq中的一些內容或使其更易於閱讀,而且我特別感興趣的是在SUT Factory容量中使用AutoFixture。
我用自己的一些關於AutoMocking的Mark Seemann的博客文章武裝自己,試圖從那裏工作,但我沒有走得很遠。
這是我的測試中看起來就像沒有AutoFixture:
[Fact]
public void GetXml_ReturnsCorrectXElement()
{
// Arrange
string xmlString = @"
<mappings>
<mapping source='gcnm_loan_amount_min' target='gcnm_loan_amount_min_usd' />
<mapping source='gcnm_loan_amount_max' target='gcnm_loan_amount_max_usd' />
</mappings>";
string settingKey = "gcCreditApplicationUsdFieldMappings";
Mock<ISettings> settingsMock = new Mock<ISettings>();
settingsMock.Setup(s => s.Get(settingKey)).Returns(xmlString);
ISettings settings = settingsMock.Object;
ITracingService tracing = new Mock<ITracingService>().Object;
XElement expectedXml = XElement.Parse(xmlString);
IMappingXml sut = new SettingMappingXml(settings, tracing);
// Act
XElement actualXml = sut.GetXml();
// Assert
Assert.True(XNode.DeepEquals(expectedXml, actualXml));
}
這裏的故事很簡單 - 確保SettingMappingXml
查詢使用正確的密鑰的ISettings
依賴(這是硬編碼/屬性注入)和返回結果爲XElement
。只有在出現錯誤時,ITracingService
纔有意義。
我想要做的是擺脫明確創建ITracingService
對象的需要,然後手動注入依賴關係(不是因爲此測試太複雜,而是因爲它足夠簡單,可以嘗試並理解它們)。
輸入AutoFixture - 第一次嘗試:
[Fact]
public void GetXml_ReturnsCorrectXElement()
{
// Arrange
IFixture fixture = new Fixture();
fixture.Customize(new AutoMoqCustomization());
string xmlString = @"
<mappings>
<mapping source='gcnm_loan_amount_min' target='gcnm_loan_amount_min_usd' />
<mapping source='gcnm_loan_amount_max' target='gcnm_loan_amount_max_usd' />
</mappings>";
string settingKey = "gcCreditApplicationUsdFieldMappings";
Mock<ISettings> settingsMock = new Mock<ISettings>();
settingsMock.Setup(s => s.Get(settingKey)).Returns(xmlString);
ISettings settings = settingsMock.Object;
fixture.Inject(settings);
XElement expectedXml = XElement.Parse(xmlString);
IMappingXml sut = fixture.CreateAnonymous<SettingMappingXml>();
// Act
XElement actualXml = sut.GetXml();
// Assert
Assert.True(XNode.DeepEquals(expectedXml, actualXml));
}
我希望CreateAnonymous<SettingMappingXml>()
,一旦檢測到ISettings
構造函數的參數,要注意到一個具體的實例已經被註冊了該接口並注入是 - 然而,它不不這樣做,而是創建一個新的匿名實現。
,這一點尤其令人混淆,因爲fixture.CreateAnonymous<ISettings>()
確實返回我的實例 -
IMappingXml sut = new SettingMappingXml(fixture.CreateAnonymous<ISettings>(), fixture.CreateAnonymous<ITracingService>());
使得測試完全綠色,此行正是我所預料AutoFixture在內部做實例SettingMappingXml
時。
再就是凍結組件的概念,所以我繼續只是凍結在夾具模擬,而不是領的嘲笑對象:
fixture.Freeze<Mock<ISettings>>(f => f.Do(m => m.Setup(s => s.Get(settingKey)).Returns(xmlString)));
果然這工作完全正常 - 只要我打電話SettingMappingXml
構造函數明確並且不依賴於CreateAnonymous()
。
簡單地說,我不明白爲什麼它的工作原理是顯然的方式做,因爲它違背了我能變出任何邏輯。 通常我會懷疑庫中存在一個bug,但這是一件非常基本的事情,我相信其他人會遇到這種情況,並且很久以前就會發現並修復它。更重要的是,瞭解Mark對測試和DI的孜孜以求,這不是無意的。
這反過來意味着我必須失去一些東西而不是基本的東西。我怎樣才能讓我的SUT通過AutoFixture創建一個預配置的模擬對象作爲依賴項?我現在唯一確定的是我需要AutoMoqCustomization
,所以我不必爲ITracingService
配置任何東西。
AutoFixture/AutoMoq包是2.14.1,Moq是3.1.416.3,全部來自NuGet。 .NET版本是4.5(與VS2012安裝),行爲是在VS2012相同,2010年
雖然寫這篇文章,我發現有些人具有起訂量4.0問題和程序集綁定重定向,所以我精心清洗我的通過將AutoFixture.AutoMoq安裝到「乾淨」項目中來安裝Moq 4的任何實例並安裝了Moq 3.1。但是,我的測試行爲保持不變。
謝謝你的指點和解釋。
更新:這裏的構造函數代碼馬克問:
public SettingMappingXml(ISettings settingSource, ITracingService tracing)
{
this._settingSource = settingSource;
this._tracing = tracing;
this.SettingKey = "gcCreditApplicationUsdFieldMappings";
}
而對於完整性,該GetXml()
方法是這樣的:
public XElement GetXml()
{
int errorCode = 10600;
try
{
string mappingSetting = this._settingSource.Get(this.SettingKey);
errorCode++;
XElement mappingXml = XElement.Parse(mappingSetting);
errorCode++;
return mappingXml;
}
catch (Exception e)
{
this._tracing.Trace(errorCode, e.Message);
throw;
}
}
SettingKey
僅僅是一個自動財產。
我無法重現你報什麼。上述測試(使用AutoFixture)在我的機器上成功。 SettingMappingXml構造函數的外觀如何? –