Метод Fixture.CreateAnonymous убивает процесс выполнения теста с ошибкой (AutoFixture) при использовании AutoMoq для создания контроллера - PullRequest
2 голосов
/ 18 августа 2010

Я пытаюсь использовать AutoMoqCustomization с AutoFixture для создания контроллера ASP.NET MVC2 в модульном тесте с помощью метода Fixture.CreateAnonymous.Я пробовал и в xUnit под TestDriven.NET, и в тестовом графическом интерфейсе xUnit, и в MSTest, и все они имеют один и тот же результат: серьезный сбой процесса, выполняющего тест.В Windows 7 x64, если это имеет значение.

Чтобы воспроизвести, просто создайте новый проект ASP.NET MVC2, добавьте ссылки на AutoFixture, AutoMoq и Moq (3.1, согласно источнику AutoMoq) и попробуйте следующее (ссылка на проект repro VS2010 MVC2 ниже):

[TestMethod]
public void Index()
{
 var fixture = new Fixture().Customize(new AutoMoqCustomization());
    // here's where the error in the test host occurs:
 HomeController controller = fixture.CreateAnonymous<HomeController>();
}

В MSTest ошибка выглядит следующим образом:

Во время выполнения произошла фатальная ошибка.Адрес ошибки был 0x6465f370 в потоке 0x2684.Код ошибки 0xc0000005.Эта ошибка может быть ошибкой в ​​CLR или в небезопасных или не поддающихся проверке частях пользовательского кода.Распространенные источники этой ошибки включают ошибки пользовательского маршалинга для COM-взаимодействия или PInvoke, которые могут повредить стек.

Проект репродукции AfWithMvc (из SkyDrive)

1 Ответ

3 голосов
/ 18 августа 2010

Предлагаемое решение

Чтобы начать с возможного решения, это должно остановить сбой:

var fixture = new Fixture().Customize(new AutoMoqCustomization());
// This should fix the problem for all Controllers
fixture.Customize<ViewDataDictionary>(c =>
    c.Without(x => x.ModelMetadata));

HomeController controller = fixture.CreateAnonymous<HomeController>();

Объяснение

А теперь для объяснения:

Эта ошибка теста вызвана функцией AutoProperties AutoFixture, пытающейся присвоить значение HomeController.ViewData.ModelMetaData.Класс ModelMetaData имеет этот конструктор:

public ModelMetadata(
    ModelMetadataProvider provider,
    Type containerType,
    Func<object> modelAccessor,
    Type modelType,
    string propertyName)

Причиной здесь является параметр modelAccessor.Чтобы заполнить это свойство, AutoFixture (скорее бездумно) отражает тип и находит этот единственный конструктор:

public Func(object @object, IntPtr method)

Копая дальше, первый конструктор IntPtr, который может удовлетворить AutoFixture, таков:

public unsafe IntPtr(int value)

По умолчанию экземпляры Int32 создаются с помощью детерминированной восходящей последовательности , поэтому value в этом случае, вероятно, будет 1 или 2 или аналогичным маленьким целым числом.Другими словами, теперь у нас есть очень недействительный небезопасный указатель в наших руках, и это приводит к сбою процесса.

Теперь, при нормальных обстоятельствах, мы должны быть в состоянии исправить это, зарегистрировавшисьFunc<object> с прибором и все должно быть модно:

fixture.Register<Func<object>>(() => () => new object());

Однако я попробовал это с вашим репро, и хотя процесс больше не падает таким же образом, тест выполняется очень долгои, наконец, вылетает с OutOfMemoryException.

Я не знаю, что ASP.NET MVC делает с Func<object>, но, видимо, он использует его довольно тяжело.

Остается вопрос, является ли этоошибка в автокреплении?

Я считаю, что это не так.Хотя это определенно не идеально, AutoFixture не обрабатывает Funcs или Actions иначе, чем другие типы, поэтому мы видим это поведение.

Это конкретное поведение может быть исправлено добавлением специальной поддержки для Func<TResult>, но чтобы оставаться согласованным, он также должен иметь поддержку Func<T, TResult>, Func<T1, T2, TResult> и т. д. AFAIR в .NET 4 есть много этих типов делегатов (также Action и т. д.), поэтомуэто означало бы добавление поддержки для целого множества типов.

Но тогда как насчет всех других типов, которые принимают IntPtr в своем конструкторе?AutoFixture, возможно, не может знать обо всех них, так что это не похоже на жизнеспособное направление.

Тем не менее, может иметь охрану , которая мешает ему попытаться создатьЭкземпляры IntPtr на первом месте .Скорее всего, это будет добавлено до версии 2.0 RTW.

Спасибо, что сообщили об этом.

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