ASP MVC V5 と属性ルーティングを使用したソリューションのテスト プロジェクトに、非常に単純なテストがあります。属性ルーティングとメソッドは、MapMvcAttributeRoutes
ASP MVC 5 の一部です。
[Test]
public void HasRoutesInTable()
{
var routes = new RouteCollection();
routes.MapMvcAttributeRoutes();
Assert.That(routes.Count, Is.GreaterThan(0));
}
結果は次のようになります:
System.InvalidOperationException :
This method cannot be called during the applications pre-start initialization phase.
このエラー メッセージに対する回答のほとんどは、web.config
ファイル内のメンバーシップ プロバイダーの構成に関係しています。このプロジェクトにはメンバーシップ プロバイダーもweb.config
ファイルもないため、エラーは他の何らかの理由で発生しているようです。テストを実行できるように、コードをこの「開始前」状態から移動するにはどうすればよいですか?
が呼び出された後、属性の同等のコードはApiController
正常に機能しますHttpConfiguration.EnsureInitialized()
。
ベストアンサー1
最近、プロジェクトをASP.NET MVC 5にアップグレードしたところ、まったく同じ問題が発生しました。ドットピーク調査してみると、コントローラー タイプのリストを期待するパラメーターMapMvcAttributeRoutes
を持つ内部拡張メソッドがあることが分かりましたIEnumerable<Type>
。リフレクションを使用して属性ベースのルートをテストできる新しい拡張メソッドを作成しました。
public static class RouteCollectionExtensions
{
public static void MapMvcAttributeRoutesForTesting(this RouteCollection routes)
{
var controllers = (from t in typeof(HomeController).Assembly.GetExportedTypes()
where
t != null &&
t.IsPublic &&
t.Name.EndsWith("Controller", StringComparison.OrdinalIgnoreCase) &&
!t.IsAbstract &&
typeof(IController).IsAssignableFrom(t)
select t).ToList();
var mapMvcAttributeRoutesMethod = typeof(RouteCollectionAttributeRoutingExtensions)
.GetMethod(
"MapMvcAttributeRoutes",
BindingFlags.NonPublic | BindingFlags.Static,
null,
new Type[] { typeof(RouteCollection), typeof(IEnumerable<Type>) },
null);
mapMvcAttributeRoutesMethod.Invoke(null, new object[] { routes, controllers });
}
}
使い方は次のとおりです:
public class HomeControllerRouteTests
{
[Fact]
public void RequestTo_Root_ShouldMapTo_HomeIndex()
{
// Arrange
var routes = new RouteCollection();
// Act - registers traditional routes and the new attribute-defined routes
RouteConfig.RegisterRoutes(routes);
routes.MapMvcAttributeRoutesForTesting();
// Assert - uses MvcRouteTester to test specific routes
routes.ShouldMap("~/").To<HomeController>(x => x.Index());
}
}
ここで問題となるのは、内部でRouteConfig.RegisterRoutes(route)
呼び出すことができないroutes.MapMvcAttributeRoutes()
ため、代わりにその呼び出しを Global.asax ファイルに移動したことです。
もう 1 つの懸念は、上記のメソッドがRouteCollectionAttributeRoutingExtensions
内部的なものであり、いつでも削除される可能性があるため、このソリューションは潜在的に脆弱であるということです。積極的なアプローチとしては、変数が null かどうかを確認しmapMvcAttributeRoutesMethod
、そうである場合は適切なエラー/例外メッセージを提供することです。
注記:これは ASP.NET MVC 5.0 でのみ機能します。ASP.NET MVC 5.1 では属性ルーティングに大幅な変更が加えられ、メソッドはmapMvcAttributeRoutesMethod
内部クラスに移動されました。