单元测试Application_Start

时间:2008-12-16 17:19:13

标签: c# asp.net-mvc unit-testing

我正在寻找有关如何在Global.asax中对Application_Start方法进行单元测试的任何类型的信息(更喜欢Moq)。我正在使用ASP.NET MVC并试图达到难以捉摸的100%代码覆盖率!

我使用MVC的事实不是重点。并且说不测试Start是不必要的也不是真正的答案。如果我有其他代码怎么办?我需要知道如何测试它。

5 个答案:

答案 0 :(得分:3)

有些组织确实需要那些毫无意义的数字,并且存在超出成本的问题。对于那些处理好的信息的公司来说,这已经足够了#34;不够好。我有完全相同的问题,像Klas Mellbourn一样,需要达到100%(如果不是更高!) 以下对我有用。虽然,我更愿意将其标记为“#34;排除代码覆盖率"

public class Global : HttpApplication
{
    public override void Init()
    {
        AreaRegistration.RegisterAllAreas(); //will error out on app_start
        base.Init();
    }

    /// <summary>
    /// Application_Start method.
    /// </summary>
    /// <param name="sender">The caller</param>
    /// <param name="e">The event arguments</param>
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "KMM: This method is called dynamically by the framework.")]
    protected void Application_Start(object sender, EventArgs e)
    {
        var container = StructureMapRegistry.Initialize();
        GlobalConfiguration.Configuration.DependencyResolver = new StructureMapResolver(container);
        GlobalConfiguration.Configure(WebApiConfig.Register);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
    }
}

然后单元测试看起来像这样:

 public class GlobalTest : Global
    {
        private HttpRequestMessage FakeRequest;

        DateTime? effectiveDate = DateTime.Now.AddYears(-4);
        private string policyNumber = "1234567890";

        [TestMethod]
        public void ApplicationStart()
        {
            var sender = new object();
            var e = new EventArgs();
            try
            {
                Application_Start(sender, e); // this will error b/c not fully loaded yet.
            }
            catch (InvalidOperationException)
            {
                Thread.Sleep(2000); // give the app time to launch

                Application_Start(sender, e);
            }
            Assert.IsTrue(true);
        }
    }

最后,我需要在我的WebApiConfig中设置一个标志,以防止路由被注册两次。

 public static class WebApiConfig
    {
        private static bool isRegistered;
        /// <summary>
        /// Registers the configuration.
        /// </summary>
        /// <param name="config">The Http Configuration.</param>
        public static void Register(HttpConfiguration config)
        {
            if (isRegistered)
            {
                return;
            }
            config.MapHttpAttributeRoutes();

现在,在仇恨者和纯粹主义者开始对此进行标记之前,分配是测试所有代码。我个人厌恶修改代码以适应测试。这与使代码可测试不同。添加isRegistered标志是支持需要调用app_start 2x的测试所必需的工件类型的示例。这是一件小事,因为该代码只能在app_start上调用,所以我不会过分夸大它。 我当然会对其他人在这方面做了什么感兴趣。

答案 1 :(得分:1)

在典型的ASP.NET MVC应用程序中,Application_Start事件通常用于注册自定义路由。这是一个很好的post,解释了如何对自定义路线进行单元测试。

答案 2 :(得分:1)

我发现在Global.asax中对单元测试内容进行单元测试的最佳方法是确保整个过程都采用可测试的静态方法。

然后从Global.asax传入该方法所需的一切。

例如,如果您正在检查Application on Application Start,您可以使用这样的方法:

public static void CheckSession(HttpSessionStateBase session)
{
...
}

然后,您的应用程序启动就是这样:

protected void Application_Start(object sender, EventArgs e)
{
    CheckSession(new HttpSessionStateWrapper(Session));
} 

这个例子显然有点傻,因为你可能会在Session Start中做这样的事情。你可以根据需要调用该方法,Request,Response,Cache等。

然而,它得到了重点。唯一不包含的代码是Application_Start中的实际单行调用。其他所有内容都可以使用Moq进行测试,如下所示:

var session = new Moq<HttpSessionStateBase>();
...Set Expectations...
Global.CheckSession(session.Object);
...Do Asserts...

你不会达到你正在寻找的100%代码覆盖率,但是你会很接近,如果不完全是这封信,你将会实现TDD法律的“精神”:)

答案 3 :(得分:0)

首次访问您的网站时会调用此函数。 回收应用程序池将导致它再次被触发

在大多数情况下,这个事件处理程序没有代码,所以不要浪费时间去追求无意义的数字!

答案 4 :(得分:0)

如果要测试像这样的基于事件的项目的操作,请将操作分成单独的可测试方法,然后从处理程序中调用它。或者,正如darin建议的那样,测试方法的效果 - 在这种特殊情况下,您的路由表已正确注册。

顺便说一句,我从来没有达到100%覆盖非平凡的应用程序...我们通常将80%的目标定为“足够好”。有些模块是100%可测试的,但许多模块都不实用。