Модульное тестирование - PullRequest
16 голосов
/ 16 декабря 2008

Я ищу любую информацию (предпочитаю Moq) о том, как выполнить модульное тестирование метода Application_Start в Global.asax. Я использую ASP.NET MVC и пытаюсь достичь этого неуловимого 100% покрытия кода!

Тот факт, что я использую MVC, не имеет значения. И сказать, что не нужно запускать тестирование, нет необходимости в ответе. Что если бы у меня был другой код? Мне нужно знать, как это проверить.

Ответы [ 5 ]

3 голосов
/ 20 июня 2014

Некоторым организациям требуются эти бессмысленные цифры, и у них возникают проблемы, не связанные с затратами. Для компаний, имеющих дело с первичной информацией, «достаточно хорошо» недостаточно. У меня была точно такая же проблема, и, как и у Klas Mellbourn, нужно добраться до 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, я не буду слишком много суетиться по этому поводу. Мне, безусловно, было бы интересно узнать, что другие сделали в этом отношении.

1 голос
/ 17 декабря 2008

Я нашел лучший способ для модульного тестирования в Global.asax - убедиться, что все это в тестируемом статическом методе.

Затем передайте этому методу все, что ему нужно, из Global.asax.

Так, например, если вы выполняете проверку сеанса при запуске приложения, у вас может быть такой метод:

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

Тогда ваш старт приложения будет следующим:

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

Этот пример, очевидно, немного глуп, поскольку вы, вероятно, сделали бы что-то подобное в Start Session :). Вы можете передать этому методу все, что ему нужно, Request, Response, Cache и т. Д.

Тем не менее, это дает понять. Единственный код, который не будет охвачен, - это фактический однострочный вызов в Application_Start. Все остальное можно описать в тесте с использованием Moq следующим образом:

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

Вы бы не достигли 100% покрытия кода, которое вы ищете, но вы были бы чертовски близки, и вы бы выполнили «дух» закона TDD, если бы не совсем буква:)

1 голос
/ 16 декабря 2008

В типичном приложении ASP.NET MVC событие Application_Start часто используется для регистрации пользовательских маршрутов. Вот хороший пост , объясняющий, как выполнить модульное тестирование ваших пользовательских маршрутов.

0 голосов
/ 16 декабря 2008

Если вы хотите проверить действия элемента, основанного на событиях, как этот, разделите действия в отдельный тестируемый метод и просто вызовите его из обработчика. Или, как предположил Дарин, протестируйте эффекты метода - в данном конкретном случае, чтобы ваша таблица маршрутизации была правильно зарегистрирована.

Кстати, я никогда не достигал 100% покрытия в нетривиальном приложении ... Обычно мы выбираем 80% как «достаточно хорошие». Некоторые модули на 100% тестируемы, но многие не практичны.

0 голосов
/ 16 декабря 2008

эта функция вызывается при первом посещении вашего сайта. переработка пула приложений приведет к его повторному запуску

В большинстве случаев этот обработчик событий не имеет кода , поэтому не тратьте время на поиск бессмысленных чисел!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...