代码之家  ›  专栏  ›  技术社区  ›  Jason

单元测试应用程序启动

  •  15
  • Jason  · 技术社区  · 16 年前

    我正在寻找关于如何在global.asax中对application_start方法进行单元测试的任何信息(更喜欢moq)。我正在使用asp.net mvc,并试图达到那难以捉摸的100%代码覆盖率!

    我使用mvc并不是重点。说不需要测试start也不是真正的答案。如果我还有其他代码呢?我需要知道如何测试它。

    5 回复  |  直到 10 年前
        1
  •  3
  •   James Fleming    10 年前

    有些组织确实需要这些毫无意义的数字,而且存在超出成本的问题。对于处理敏感信息的公司来说,“足够好”还不够好。我也有同样的问题,像克拉斯·梅尔伯恩一样,需要达到100%(如果不是更高的话!) 下面的对我有用。不过,我宁愿把它标记为“排除在代码覆盖范围之外”

    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上调用,所以我不会为它太操心。 我当然对其他人在这方面所做的工作感兴趣。

        2
  •  1
  •   CubanX    12 年前

    我已经找到了在global.asax中进行单元测试的最佳方法,就是确保整个过程都在一个可测试的静态方法中。

    然后把它需要的一切从global.asax传递给那个方法。

    例如,如果在应用程序启动时检查会话,则可以使用以下方法:

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

    然后,您的应用程序将开始如下:

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

    这个示例显然有点傻,因为您可能会在session start中执行类似的操作:)您可以将所需的任何内容、请求、响应、缓存等传递给该方法。

    然而,这一点得到了理解。唯一没有涉及到的代码是application\u start中的实际单行调用。其他一切都可以在使用moq的测试中涵盖,如下所示:

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

    你不可能达到你想要的100%的代码覆盖率,但是你已经很接近了,而且你将实现TDD法律的“精神”,如果不是确切的字母:)

        3
  •  1
  •   SteveC    11 年前

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

        4
  •  0
  •   Steven A. Lowe    16 年前

    此函数在第一次访问站点时调用。 回收应用程序池将导致它再次被触发

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

        5
  •  0
  •   GalacticCowboy    16 年前

    如果要测试基于事件的项的操作,请将这些操作分离为单独的、可测试的方法,然后从处理程序调用它。或者,正如达林建议的那样,测试 影响 在这个特殊的例子中,你的路由表被正确注册了。

    顺便说一句,我从来没有在一个不起眼的应用上达到100%的覆盖率…我们通常把80%的目标定为“足够好”。有些模块是100%可测试的,但许多模块不实用。