MvcIntegrationTestFramework или альтернатива обновлена ​​для ASP.NET MVC 3 - PullRequest
18 голосов
/ 25 ноября 2010

Мне интересно использовать MvcIntegrationTestFramework Стива Сандерсона или очень похожую альтернативу с ASP.NET MVC 3 Beta.

В настоящее время при компиляции MvcIntegrationTestFramework против MVC 3 Beta я получаю следующую ошибку из-за изменений в MVC:

Error 6 'System.Web.Mvc.ActionDescriptor.GetFilters()' is obsolete: '"Please call System.Web.Mvc.FilterProviders.Providers.GetFilters() now."' \MvcIntegrationTestFramework\Interception\InterceptionFilterActionDescriptor.cs Line 18

Вопросы

1. Кто-нибудь может предоставить MvcIntegrationTestFramework, работающий для ASP.NET MVC 3 Beta?

--- и / или ---

2. Вы бы порекомендовали похожие варианты?


РЕДАКТИРОВАТЬ # 1: Примечание Я отправил электронное письмо Стиву, создателю MvcIntegrationTestFramework, также надеясь получить некоторую обратную связь там.

РЕДАКТИРОВАТЬ # 2 & # 3: Я получил сообщение от Стива. Цитируется для справки:
Мне не нужно было использовать этот проект с MVC 3, поэтому извините, у меня нет его обновленной версии. Насколько мне известно, должно быть возможно обновить его для работы в MVC 3, но вам, возможно, потребуется выяснить это, изучив исходный код MVC 3, чтобы заметить любые изменения в том, как вызываются действия, фильтры и т. Д. сейчас. Если вы обновите его и решите принять его за текущий проект (например, поместить его на Github или аналогичный), дайте мне знать, и я опубликую ссылку на него! (Спасибо, Стив!)

РЕДАКТИРОВАТЬ # 4: Честно говоря, быстрый удар по использованию System.Web.Mvc.FilterProviders.Providers.GetFilters() никуда не делся быстро, и простое добавление [Obsolete] обнаружило, что во внутренних запросах MVC была ошибка. У кого-нибудь еще был баловство?

РЕДАКТИРОВАТЬ # 5: Пожалуйста, прокомментируйте, если вы используете альтернативную интеграционную среду тестирования с MVC 3.

Ответы [ 4 ]

9 голосов
/ 16 марта 2011

Посмотрите на мою вилку:

https://github.com/JonCanning/MvcIntegrationTestFramework/

4 голосов
/ 16 декабря 2010

Я понимаю, что это не тот ответ, который вы ищете, но Selenium или Watin могут быть вам полезны в качестве альтернативы Integration Test Framework.

Selenium позволит вам записывать тесты в виде nUnit-кода, чтобы вы могли интегрироваться с вашими существующими тестовыми проектами и т. Д. Затем ваш тест может проверить DOM аналогично Integration Test Framework. Преимущество заключается в том, что тесты Selenium могут выполняться в различных браузерах.

Ключевое предостережение заключается в том, что Selenium необходимо, чтобы ваше приложение было развернуто на веб-сервере, но вы не уверены, что для вас это ограничитель показа.

1 голос
/ 15 декабря 2012

Я подумал, что поделюсь своим опытом использования MvcIntegrationTestFramework в проекте ASP.NET MVC 4. В частности, проект ASP.NET MVC 4 представлял собой веб-роль для облачной службы Windows Azure .

Хотя пример проекта из форка Джона Каннинга работал для меня (хотя я изменил сборку System.Web.Mvc с 3.0.0.0 на 4.0.0.0, что потребовало кучу редактирования в файле web.config, чтобы получить запускать и проходить тесты) я получал сообщение об ошибке при попытке запустить те же тесты для проекта веб-роли Azure ASP.NET MVC 4. Ошибка была:

System.Reflection.TargetInvocationException: Исключение было сгенерировано целью вызова.

Внутреннее исключение было:

System.InvalidOperationException: этот метод не может быть вызван во время предварительной инициализации приложения.

Мне стало интересно, чем проект Azure Web Role, основанный на ASP.NET MVC 4, отличается от обычного проекта ASP.NET MVC 4, и как такое различие может вызвать эту ошибку. Я немного поискал в интернете, но не встречал никого, кто пытался сделать то же самое, что и я. Вскоре мне удалось понять, что это было связано с Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener . Часть роли этого класса, по-видимому, состоит в том, чтобы гарантировать, что веб-роль выполняется в размещенной службе или в среде разработки (вы увидите сообщение об этом, если переключите проект запуска из проект облачной службы для проекта веб-роли внутри решения облачной службы, а затем попробуйте отладку).

Решение ? Я удалил соответствующий прослушиватель из файла Web.config моего проекта веб-роли:

<configuration>
... 
  <system.diagnostics>
    <trace>
      <listeners>
        <!--Remove this next 'add' element-->
        <add type="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Microsoft.WindowsAzure.Diagnostics, Version=1.8.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
      name="AzureDiagnostics"> <filter type="" /> </add> 
      </listeners>
    </trace>
  </system.diagnostics>
...
</configuration>

Затем я смог запустить интеграционные тесты в обычном режиме для моего проекта веб-роли. Однако я добавил слушателя в файлы преобразования Web.Debug.config и Web.Release.config, чтобы при обычном развертывании и отладке все было по-прежнему.

Возможно, это поможет кому-то, желающему использовать MvcIntegrationTestFramework для разработки на Azure.

EDIT Я только что понял, что это решение может быть чем-то вроде «хака», потому что оно может не позволить вам провести интеграционное тестирование кода приложения, связанного с компонентами Azure (например, возможно, со специальными механизмами кэширования Azure). Тем не менее, я еще не сталкивался с какими-либо проблемами, связанными с этим, хотя я также еще не написал так много интеграционных тестов ...

0 голосов
/ 09 июня 2012

Я использовал обновленную версию Джона Каннинга (https://github.com/JonCanning/MvcIntegrationTestFramework/)), и она очень хорошо решила мою проблему для методов контроллера, которые принимают только типы значений и строки, но не работают для тех, которые принимают классы.

Оказывается, возникла проблема с кодом для обновленного MvcIntegrationTestFramework.

Я понял, как это исправить, но не знаю, где еще можно опубликовать решение, поэтому вот оно:

Простой пример того, как это работает:

    [TestMethod]
    public void Account_LogOn_Post_Succeeds()
    {
        string loginUrl = "/Account/LogOn";
        appHost.Start(browsingSession =>
        {
            var formData = new RouteValueDictionary
            {
                { "UserName", "myusername" },
                { "Password", "mypassword" },
                { "RememberMe", "true"},
                { "returnUrl", "/myreturnurl"},
            };

            RequestResult loginResult = browsingSession.Post(loginUrl, formData);

            // Add your test assertions here.
        });
    }

Вызов browsingSession.Post в конечном итоге вызовет метод NameValueCollectionConversions.ConvertFromRouteValueDictionary(object anonymous), и код для этого будет:

public static class NameValueCollectionConversions
{
    public static NameValueCollection ConvertFromObject(object anonymous)
    {
        var nvc = new NameValueCollection();
        var dict = new RouteValueDictionary(anonymous); // ** Problem 1

        foreach (var kvp in dict)
        {
            if (kvp.Value == null)
            {
                throw new NullReferenceException(kvp.Key);
            }
            if (kvp.Value.GetType().Name.Contains("Anonymous"))
            {
                var prefix = kvp.Key + ".";
                foreach (var innerkvp in new RouteValueDictionary(kvp.Value))
                {
                    nvc.Add(prefix + innerkvp.Key, innerkvp.Value.ToString());
                }
            }
            else
            {
                nvc.Add(kvp.Key, kvp.Value.ToString()); // ** Problem2
            }
        }
        return nvc;
    }

Тогда возникли две проблемы:

  1. Вызов new RouteValueDictionary(anonymous) вызовет создание "нового" RouteValueDictionary, но вместо 4 ключей будет только три, один из которых был массивом из 4 элементов.
  2. Когда он попадает в эту строку: nvc.Add(kvp.Key, kvp.Value.ToString(), kvp.Value является массивом, и ToString () дает: "System.Collections.Generic.Dictionary'2+ValueCollection[System.String,System.Object]"

Исправление (к моей конкретной проблеме) было изменить код следующим образом:

        var dict = anonymous as RouteValueDictionary; // creates it properly
        if (null == dict)
        {
            dict = new RouteValueDictionary(anonymous);             
        }

После того, как я внес это изменение, мой класс модели будет правильно связываться, и все будет хорошо.

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