3

AutoFixtureでAutoMoqCustomizationを使用して、Fixture.CreateAnonymousメソッドを介した単体テストでASP.NETMVC2コントローラーを作成しようとしています。TestDriven.NETのxUnit、xUnitテストGUI、およびMSTestの両方で試しましたが、すべて同じ結果になりました。テストを実行するプロセスの大規模な失敗です。それが重要な場合は、Windows7x64で。

再現するには、新しいASP.NET MVC2プロジェクトを作成し、AutoFixture、AutoMoq、およびMoq(AutoMoqソースによる3.1)への参照を追加して、以下を試してください(以下の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では、エラーは次のようになります。

ランタイムで致命的なエラーが発生しました。エラーのアドレスは、スレッド0x2684の0x6465f370にありました。エラーコードは0xc0000005です。このエラーは、CLRのバグ、またはユーザーコードの安全でない部分または検証できない部分のバグである可能性があります。このバグの一般的な原因には、COM-interopまたはPInvokeのユーザーマーシャリングエラーがあり、スタックが破損する可能性があります。

AfWithMvc再現プロジェクト(SkyDriveから)

4

1 に答える 1

4

推奨される解決策

考えられる解決策から始めるには、これでクラッシュが停止するはずです。

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>、フィクスチャにaを登録することでこれを修正できるはずであり、すべてがダンディである必要があります。

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>。.NET4のAFAIRには、これらのデリゲートタイプ(アクションなど)が多数あるためさまざまなタイプのサポートを追加することを意味します。

しかし、コンストラクターでIntPtrを使用する他のすべての型についてはどうでしょうか。AutoFixtureはそれらすべてを知ることはできないので、これは実行可能な方向ではないようです。

ただし、それが持つ可能性があるのは、そもそもIntPtrインスタンスを作成しようとするのを防ぐガードです。これは、2.0RTWより前に追加される可能性があります。

これを報告していただきありがとうございます。

于 2010-08-18T19:57:13.470 に答える