Ant*_*ony 35 asp.net-mvc unit-testing attributerouting asp.net-mvc-5
在使用ASP MVC V5和属性路由的解决方案中,我在测试项目中进行了非常简单的测试.属性路由和MapMvcAttributeRoutes方法是ASP MVC 5的一部分.
[Test]
public void HasRoutesInTable()
{
var routes = new RouteCollection();
routes.MapMvcAttributeRoutes();
Assert.That(routes.Count, Is.GreaterThan(0));
}
Run Code Online (Sandbox Code Playgroud)
这导致:
System.InvalidOperationException :
This method cannot be called during the applications pre-start initialization phase.
Run Code Online (Sandbox Code Playgroud)
此错误消息的大多数答案涉及在web.config文件中配置成员资格提供程序.该项目既没有成员资格提供者也没有web.config文件,因此出于某种其他原因似乎发生了错误.如何将代码移出此"预启动"状态以便测试可以运行?
调用ApiController后的工作属性的等效代码HttpConfiguration.EnsureInitialized().
Ste*_*ven 19
我最近将我的项目升级到ASP.NET MVC 5并遇到了完全相同的问题.当使用dotPeek进行调查时,我发现有一个内部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 });
}
}
Run Code Online (Sandbox Code Playgroud)
以下是我如何使用它:
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());
}
}
Run Code Online (Sandbox Code Playgroud)
现在的一个问题是RouteConfig.RegisterRoutes(route)我无法调用内部,routes.MapMvcAttributeRoutes()因此我将该调用移至我的Global.asax文件中.
另一个问题是这种解决方案可能很脆弱,因为上述方法RouteCollectionAttributeRoutingExtensions是内部的,可以随时删除.主动方法是检查mapMvcAttributeRoutesMethod变量是否为空,并提供适当的错误/异常消息(如果是).
注意:这仅适用于ASP.NET MVC 5.0.ASP.NET MVC 5.1中的属性路由发生了重大更改,并且该mapMvcAttributeRoutesMethod方法已移至内部类.
在ASP.NET MVC 5.1这个功能被转移到自己的类叫AttributeRoutingMapper.
(这就是为什么不应该依赖于内部类中的代码攻击)
但这是5.1(以及?)的解决方法:
public static void MapMvcAttributeRoutes(this RouteCollection routeCollection, Assembly controllerAssembly)
{
var controllerTypes = (from type in controllerAssembly.GetExportedTypes()
where
type != null && type.IsPublic
&& type.Name.EndsWith("Controller", StringComparison.OrdinalIgnoreCase)
&& !type.IsAbstract && typeof(IController).IsAssignableFrom(type)
select type).ToList();
var attributeRoutingAssembly = typeof(RouteCollectionAttributeRoutingExtensions).Assembly;
var attributeRoutingMapperType =
attributeRoutingAssembly.GetType("System.Web.Mvc.Routing.AttributeRoutingMapper");
var mapAttributeRoutesMethod = attributeRoutingMapperType.GetMethod(
"MapAttributeRoutes",
BindingFlags.Public | BindingFlags.Static,
null,
new[] { typeof(RouteCollection), typeof(IEnumerable<Type>) },
null);
mapAttributeRoutesMethod.Invoke(null, new object[] { routeCollection, controllerTypes });
}
Run Code Online (Sandbox Code Playgroud)
好吧,它真的很难看,我不确定它是否值得测试复杂性,但是如果不修改你的RouteConfig.Register代码就可以做到这一点:
[TestClass]
public class MyTestClass
{
[TestMethod]
public void MyTestMethod()
{
// Move all files needed for this test into a subdirectory named bin.
Directory.CreateDirectory("bin");
foreach (var file in Directory.EnumerateFiles("."))
{
File.Copy(file, "bin\\" + file, overwrite: true);
}
// Create a new ASP.NET host for this directory (with all the binaries under the bin subdirectory); get a Remoting proxy to that app domain.
RouteProxy proxy = (RouteProxy)ApplicationHost.CreateApplicationHost(typeof(RouteProxy), "/", Environment.CurrentDirectory);
// Call into the other app domain to run route registration and get back the route count.
int count = proxy.RegisterRoutesAndGetCount();
Assert.IsTrue(count > 0);
}
private class RouteProxy : MarshalByRefObject
{
public int RegisterRoutesAndGetCount()
{
RouteCollection routes = new RouteCollection();
RouteConfig.RegisterRoutes(routes); // or just call routes.MapMvcAttributeRoutes() if that's what you want, though I'm not sure why you'd re-test the framework code.
return routes.Count;
}
}
}
Run Code Online (Sandbox Code Playgroud)
映射属性路由需要找到您用于获取其属性的所有控制器,这需要访问构建管理器,该管理器显然仅适用于为ASP.NET创建的应用程序域.
ozc*_*cho -5
你在这里测试什么?看起来您正在测试第三方扩展方法。您不应该使用单元测试来测试第三方代码。
| 归档时间: |
|
| 查看次数: |
14632 次 |
| 最近记录: |