Ответ 1
Посмотрите на мою вилку:
Мне интересно использовать Steve Sandersons 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, также надеясь на некоторую обратную связь.
EDIT # 2 и # 3: Я получил сообщение от Стива. Цитируется по ссылке:
Мне не нужно было использовать этот проект с MVC 3, так что извините, у меня нет обновленной версии. Насколько мне известно, должно быть возможно обновить его для работы с MVC 3, но вам нужно будет понять это, возможно, проверив исходный код MVC 3, чтобы заметить какие-либо изменения в действии действий, фильтров и т.д. Теперь. Если вы его обновите, и если вы решите принять его в качестве текущего проекта (например, положив его на Github или аналогичный), сообщите мне, и я отправлю ему ссылку! (Спасибо Стив!)
РЕДАКТИРОВАТЬ № 4: Честно быстрая атака при использовании System.Web.Mvc.FilterProviders.Providers.GetFilters()
не ускорилась и просто добавила [Obsolete]
, что была ошибка во внутренних сообщениях MVC-запросов, У кого-нибудь еще была ошибка?
РЕДАКТИРОВАТЬ № 5: Прокомментируйте, если вы используете альтернативную тестовую платформу интеграции с MVC 3.
Посмотрите на мою вилку:
Я понимаю, что это не тот ответ, который вы ищете, но Selenium или Watin могут вам пригодиться в качестве альтернативы Integration Test Framework.
Selenium позволит вам записывать тесты как код nUnit, чтобы вы могли интегрироваться с существующими тестовыми проектами и т.д. Затем ваш тест может проверить DOM аналогично Framework Integration Test Framework. Преимущество Selenium-тестов может быть выполнено с различными браузерами.
Предостережение о том, что Selenium необходимо, чтобы ваше приложение было развернуто на веб-сервере, не уверен, что это шоу-стоп для вас.
Я думал, что поделился бы опытом использования MvcIntegrationTestFramework в проекте ASP.NET MVC 4. В частности, проект ASP.NET MVC 4 был веб-ролью для облачной службы Windows Azure.
Хотя проект проекта из вилки Джона Коннинга работал у меня (хотя я изменил сборку System.Web.Mvc от 3.0.0 до 4.0.0.0, что потребовало кучу редактирования в файле web.config, чтобы получить тесты для запуска и передачи), я получил сообщение об ошибке, когда пытался запустить те же тесты с проектом Azure ASP.NET MVC 4 Web Role. Ошибка:
System.Reflection.TargetInvocationException: Исключение выбрано целевым объектом вызова.
Внутреннее исключение:
System.InvalidOperationException: этот метод не может быть вызван во время фазы инициализации перед запуском приложения.
Мне стало интересно, как проект Azure Web Role на основе ASP.NET MVC 4 отличается от обычного проекта ASP.NET MVC 4 и как такая разница может вызвать эту ошибку. Я немного искал в Интернете, но не сталкивался с тем, что кто-то пытался сделать то же самое, что и я. Вскоре я понял, что это связано с Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener. Часть роли этого класса, по-видимому, заключается в обеспечении того, чтобы роль веб-сайта выполнялась в размещенной службе или в Fabric Development (вы увидите сообщение об этом, если вы переключите проект запуска из проекта облачной службы на веб-сайт ролевой проект внутри облачного сервисного решения, а затем попытайтесь отладить).
Решение? Я удалил соответствующий прослушиватель из файла 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.
ИЗМЕНИТЬ Я просто понял, что это решение может быть немного "взломанным", потому что это может не позволить вам протестировать интеграцию с кодом приложения, который относится к компонентам Azure (например, могут использоваться специальные механизмы кэширования Azure). Тем не менее, я еще не сталкивался с какими-либо проблемами, хотя я еще не писал, что многие интеграционные тесты еще...
Я использовал обновленную версию Jon Canning (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;
}
Тогда возникли две проблемы:
new RouteValueDictionary(anonymous)
приведет к созданию "нового" RouteValueDictionary
, но вместо 4 ключей будет только три, один из которых представляет собой массив из 4 элементов.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);
}
После того, как я сделал это изменение, мой класс модели будет правильно привязан, и все будет хорошо.