2010-08-18 20 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

相关问题