C# 当使用AutoMoq创建控制器时,Fixture.CreateAnonymous方法以错误(AutoFixture)终止测试运行程序进程

C# 当使用AutoMoq创建控制器时,Fixture.CreateAnonymous方法以错误(AutoFixture)终止测试运行程序进程,c#,unit-testing,asp.net-mvc-2,autofixture,C#,Unit Testing,Asp.net Mvc 2,Autofixture,我正在尝试使用AutoFixture的AutoMoqCustomization通过Fixture.CreateAnonymous方法在单元测试中创建ASP.NET MVC2控制器。我在TestDriven.NET下的xUnit、xUnit测试GUI和MSTest中都进行了尝试,结果都是一样的:运行测试的进程出现了巨大的失败。在Windows7x64上,如果这很重要的话 要复制,只需创建一个新的ASP.NET MVC2项目,添加对AutoFixture、AutoMoq和Moq的引用(3.1,根据A

我正在尝试使用AutoFixture的AutoMoqCustomization通过Fixture.CreateAnonymous方法在单元测试中创建ASP.NET MVC2控制器。我在TestDriven.NET下的xUnit、xUnit测试GUI和MSTest中都进行了尝试,结果都是一样的:运行测试的进程出现了巨大的失败。在Windows7x64上,如果这很重要的话

要复制,只需创建一个新的ASP.NET MVC2项目,添加对AutoFixture、AutoMoq和Moq的引用(3.1,根据AutoMoq源),然后尝试以下操作(下面的repro VS2010 MVC2项目链接):

[TestMethod]
公共空间索引()
{
var fixture=new fixture().Customize(new AutoMoqCustomization());
//以下是测试主机中发生错误的地方:
HomeController控制器=fixture.CreateAnonymous();
}
在MSTest中,错误显示为:

运行时遇到致命错误。错误地址位于线程0x2684上的0x6465f370。错误代码为0xc0000005。此错误可能是CLR或用户代码的不安全或不可验证部分中的错误。此错误的常见来源包括COM互操作或PInvoke的用户封送错误,这可能会损坏堆栈


建议的解决方案

要从一个可能的解决方案开始,应该停止崩溃:

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>();
罪魁祸首是
modelacessor
参数。要填充该属性,AutoFixture(相当无意识地)会反映类型并找到此单个构造函数:

public ModelMetadata(
    ModelMetadataProvider provider,
    Type containerType,
    Func<object> modelAccessor,
    Type modelType,
    string propertyName)
public Func(object @object, IntPtr method)
进一步挖掘,第一个IntPtr构造函数AutoFixture可以满足以下要求:

public unsafe IntPtr(int value)
默认情况下,因此本例中的
值可能是1或2或类似的小整数。换句话说,我们现在手上有一个非常无效的不安全指针,这使得进程崩溃

现在,在正常情况下,我们应该能够通过在夹具上注册
Func
来解决这个问题,并且一切都应该很好:

fixture.Register<Func<object>>(() => () => new object());
fixture.Register(()=>()=>newobject());
然而,我用你的复制程序尝试了这个方法,虽然这个过程不再以同样的方式崩溃,但是测试运行了很长时间,最后崩溃了,出现了OutOfMemoryException

我不知道ASP.NETMVC对
Func
做了什么,但显然它的使用量很大

问题仍然是这是否是AutoFixture中的一个bug

我相信不是。虽然AutoFixture显然不太理想,但它对函数或动作的处理与其他类型没有任何不同,这就是我们看到这种行为的原因

可以通过添加对
Func
的特定支持来解决此特定行为,但为了保持一致,它还应该支持
Func
Func
等。AFAIR在.NET 4中有许多这样的委托类型(还有操作等),因此这意味着添加对整个类型主机的支持

但是其他所有在构造函数中使用IntPtr的类型呢?AutoFixture不可能完全了解它们,所以这似乎不是一个可行的方向

然而,它可能会有一个新的选择。这很可能是在2.0 RTW之前添加的


谢谢您的报道。

谢谢,这是一个很好的解释和修正。值得一提的是,我同意您的观点,即应该保护IntPtr,但不应该添加任何特定于代理的支持-似乎没有必要。好的,我使用fixture.Inject(..)进行了研究,并在它和MVC2源之间,发现MVC框架要求在某个点从Func返回null作为终止符/信号。它可以从开始处返回null,也可以返回n个字符串,然后返回null。
fixture.Register<Func<object>>(() => () => new object());