2010-08-18 35 views
2

我試圖使用AutoMoqCustomization和AutoFixture通過Fixture在單元測試中創建ASP.NET MVC2控制器。 CreateAnonymous方法。我已經在xUnit下的TestDriven.NET,xUnit測試GUI和MSTest中嘗試過,並且都具有相同的結果:運行測試的過程出現嚴重故障。在Windows 7 x64上如果有問題。Fixture.CreateAnonymous方法使用AutoMoq創建控制器時會導致測試運行器進程出現錯誤(AutoFixture)

要重現,只需創建一個新的ASP.NET MVC2項目,添加到AutoFixture,AutoMoq和起訂量的參考(3.1,按照該AutoMoq源),並嘗試以下(攝製VS2010 MVC2項目下面的鏈接):

[TestMethod] 
public void Index() 
{ 
var fixture = new Fixture().Customize(new AutoMoqCustomization()); 
    // here's where the error in the test host occurs: 
HomeController controller = fixture.CreateAnonymous<HomeController>(); 
} 

在MSTest的錯誤讀取:

運行時遇到一個致命錯誤。錯誤的地址是0x6465f370,位於線程0x2684。錯誤代碼是0xc0000005。此錯誤可能是CLR中的錯誤,也可能是用戶代碼中不安全或不可驗證的部分。此錯誤的常見來源包括COM-interop或PInvoke的用戶編組錯誤,這可能會破壞堆棧。

AfWithMvc repro project (from SkyDrive)

回答

3

建議的解決方案

要開始一個可能的解決方案,這應該停止崩潰:

var fixture = new Fixture().Customize(new AutoMoqCustomization()); 
// This should fix the problem for all Controllers 
fixture.Customize<ViewDataDictionary>(c => 
    c.Without(x => x.ModelMetadata)); 

HomeController controller = fixture.CreateAnonymous<HomeController>(); 

說明

而現在的解釋:

此測試錯誤是由AutoFixture的AutoProperties功能試圖爲HomeController.ViewData.ModelMetaData指定一個值。該ModelMetaData類有這樣的構造:

public ModelMetadata(
    ModelMetadataProvider provider, 
    Type containerType, 
    Func<object> modelAccessor, 
    Type modelType, 
    string propertyName) 

這裏的罪魁禍首是modelAccessor參數。爲了填補這個屬性AutoFixture(而不是盲目地)反映了類型,並認爲這一個構造函數:

public Func(object @object, IntPtr method) 

進一步挖掘,第一IntPtr的構造AutoFixture能滿足這一個:

public unsafe IntPtr(int value) 

默認情況下, Int32 instances are created by a deterministic rising sequence,所以在這種情況下value可能會是1或2或類似的小整數。換句話說,我們現在有一個非常無效的不安全的指針,這使得進程崩潰。

現在,一般情況下,我們應該能夠通過註冊與該固定物Func<object>解決這個問題,一切都應該是花花公子:

fixture.Register<Func<object>>(() =>() => new object()); 

不過,我想這與你的攝製,雖然過程中不再以相同的方式崩潰,測試運行很長時間,並最終崩潰與OutOfMemoryException。

我不知道ASP.NET MVC用Func<object>做什麼,但顯然它使用它相當重。

問題是這是否是AutoFixture中的錯誤?

我相信它不是。雖然它絕對不是理想的,但AutoFixture不會將Funcs或Actions與其他類型視爲不同,這就是我們看到這種行爲的原因。

這種特殊的行爲可能會因增加了對Func<TResult>特定支持來解決,而是留Func<T, TResult>一致的,也應該有支持,Func<T1, T2, TResult>等AFAIR在.NET 4中有很多這些委託類型(還有Action等),所以這意味着需要添加對大量類型的支持。

但是那麼在構造函數中採用IntPtr的所有其他類型呢? AutoFixture不可能全部瞭解它們,所以這看起來不像一個可行的方向。

但是,可能具有的是guard that prevents it from attempting to create IntPtr instances in the first place。這很可能會在2.0 RTW之前添加。

謝謝你報告這個。

+0

謝謝,這是一個很好的解釋和修復。對於它的價值,我同意你的想法,即應該保護IntPtr,但不應該增加代表特定的支持 - 似乎沒有必要。 – ZeroBugBounce 2010-08-18 20:06:25

+0

好的,我玩弄fixture.Inject >(..)以及該和MVC2源之間,發現MVC框架要求null作爲終止符/信號從Func 返回。 它可以從開始返回null或返回n個字符串,然後爲null。 – ZeroBugBounce 2010-08-18 20:20:34

相關問題