使用AutoMoq创建控制器时,Fixture.CreateAnonymous方法使用错误(AutoFixture)杀死测试运行程序进程
我正在尝试使用AutoMoqCustomization和AutoFixture通过Fixture.CreateAnonymous方法在unit testing中创建ASP.NET MVC2控制器。 我在TestDriven.NET下的xUnit,xUnit测试GUI和MSTest中都尝试过,并且都有相同的结果:运行测试的过程发生了大量故障。 在Windows 7 x64上,如果这很重要。
要重现,只需创建一个新的ASP.NET MVC2项目,添加对AutoFixture,AutoMoq和Moq(3.1,根据AutoMoq源)的引用,并尝试下面的(下面的repro 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(); }
在MSTest中,错误如下:
运行时遇到了致命错误。 错误的地址是0x6465f370,位于线程0x2684。 错误代码是0xc0000005。 此错误可能是CLR中的错误,也可能是用户代码的不安全或不可validation部分中的错误。 此错误的常见来源包括COM-interop或PInvoke的用户封送错误,这可能会破坏堆栈。
AfWithMvc repro项目(来自SkyDrive)
建议的解决方案
要从可能的解决方案开始,这应该停止崩溃:
var fixture = new Fixture().Customize(new AutoMoqCustomization()); // This should fix the problem for all Controllers fixture.Customize(c => c.Without(x => x.ModelMetadata)); HomeController controller = fixture.CreateAnonymous();
说明
现在解释一下:
此测试错误是由AutoFixture的AutoPropertiesfunction尝试为HomeController.ViewData.ModelMetaData
分配值引起的。 ModelMetaData类具有以下构造函数:
public ModelMetadata( ModelMetadataProvider provider, Type containerType, Func
这里的罪魁祸首是modelAccessor
参数。 为了填充该属性,AutoFixture(相当无意识地)反映了该类型并找到了这个单一的构造函数:
public Func(object @object, IntPtr method)
进一步挖掘,第一个IntPtr构造函数AutoFixture可以满足这一个:
public unsafe IntPtr(int value)
默认情况下, Int32实例由确定性上升序列创建 ,因此在这种情况下, value
可能是1或2或类似的小整数。 换句话说,我们现在手上有一个非常无效的不安全指针,这使得进程崩溃。
现在,在正常情况下,我们应该能够通过使用Fixture注册Func
来解决这个问题,一切都应该是花花公子:
fixture.Register>(() => () => new object());
但是,我尝试使用你的repro,尽管进程不再以相同的方式崩溃,但测试运行了很长时间,最后崩溃并出现OutOfMemoryException。
我不知道ASP.NET MVC使用Func
做了什么,但显然它使用它非常重。
问题仍然是这是否是AutoFixture中的错误?
我相信事实并非如此。 虽然它绝对不太理想,但AutoFixture并不会将Funcs或Actions与其他类型区别对待,这就是我们看到这种行为的原因。
这种特殊行为可以通过添加对Func
特定支持来解决,但为了保持一致,它还应该支持Func
, Func
等.AFFI在.NET 4中有很多这些委托类型(也是Action等),因此这意味着要添加对整个类型的支持。
但那么在构造函数中采用IntPtr的所有其他类型呢? AutoFixture可能无法全部了解它们,所以这似乎不是一个可行的方向。
但是,它可能具有的防护措施可以防止它首先尝试创建IntPtr实例 。 这很可能会在2.0 RTW之前添加。
感谢您报告此事。
- .NET 4 MVC 2使用注释警告而不是错误进行validation
- 使用Moq模拟HttpContext.Current.Server.MapPath?
- 根据列值-linq删除Duplicate
- MVC2 ASP.Net URL会自动解码吗?
- 在MvcSiteMapProvider中为具有动态参数的DynamicNode创建子节点
- 为什么Ajax.BeginForm不能在Chrome中运行?
- 如何从asp.net mvc 2应用程序中的自定义ValidationAttribute内部访问其他属性值?
- ASP.NET MVC 2中具有一个名称的多个控制器
- HTML敏捷包 – 如何在Head元素的顶部追加元素?