建议的解决方案
从一个可能的解决方案开始,这应该会阻止崩溃:
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)
进一步挖掘,AutoFixture 可以满足的第一个 IntPtr 构造函数是:
public unsafe IntPtr(int value)
默认情况下,Int32 实例由确定性上升序列创建,因此value
在这种情况下可能是 1 或 2 或类似的小整数。换句话说,我们现在手上有一个非常无效的不安全指针,这导致进程崩溃。
现在,在正常情况下,我们应该能够通过Func<object>
向 Fixture 注册 a 来解决此问题,并且一切都应该是花花公子:
fixture.Register<Func<object>>(() => () => new object());
但是,我用您的复制品尝试了这个,虽然该过程不再以相同的方式崩溃,但测试运行了很长时间,最终崩溃并出现 OutOfMemoryException。
我不知道 ASP.NET MVC 对 ASP.NET MVC 做了什么Func<object>
,但显然它使用得非常频繁。
问题仍然是这是否是 AutoFixture 中的错误?
我相信它不是。虽然它绝对不够理想,但 AutoFixture 对待 Funcs 或 Action 的方式与其他类型没有任何不同,这就是我们看到这种行为的原因。
这种特殊的行为可以通过添加对 的特定支持来解决Func<TResult>
,但为了保持一致,它还应该支持Func<T, TResult>
,Func<T1, T2, TResult>
等。AFAIR 在 .NET 4 中有很多这样的委托类型(还有 Action 等),所以意味着增加对一大堆类型的支持。
但是,所有其他在其构造函数中采用 IntPtr 的类型呢?AutoFixture 不可能知道所有这些,所以这似乎不是一个可行的方向。
然而,它可能拥有的是一个防止它首先尝试创建 IntPtr 实例的守卫。这很可能会在 2.0 RTW 之前添加。
感谢您报告此事。