Рег.Модульное тестирование Html Helper с автофиксом - PullRequest
3 голосов
/ 12 сентября 2011

Оригинальный вопрос: Модульное тестирование Html-помощника с автофиксом

Не уверен, что мне следует заново открыть исходный вопрос; однако, так как я отметил исходный вопрос как решенный, я решил создать новый. Извиняюсь, если я сделал это неправильно.

Я использовал предложенный Марком подход, но застрял при использовании Freeze.

Ниже приведен полный исходный код ... Тестируемый класс:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MvcDemo2.Helpers
{
      public static class Keys
      {
          public static readonly string SomeKey = "SomeKey";
      }

      public static class SampleHelpers
      {
          public static MvcHtmlString SampleTable(this HtmlHelper helper, 
            SampleModel model, IDictionary<string, object> htmlAttributes)
          {
                if (helper == null)
                {
                    throw new ArgumentNullException("helper");
                }

                if (model == null)
                {
                    throw new ArgumentNullException("model");
                }

                TagBuilder tagBuilder = new TagBuilder("table");
                tagBuilder.MergeAttributes(htmlAttributes);                               
                tagBuilder.GenerateId(helper.ViewContext.
                                 HttpContext.Items[Keys.SomeKey].ToString());
                return MvcHtmlString.Create(
                         tagBuilder.ToString(TagRenderMode.Normal));
            }
      }
  }


  public class SampleModel
  {
  }
}

Модульный тест должен гарантировать, что Html вернется, как и ожидалось, для указанного ключа в HttpContext

public void SampleTableHtmlHelper_WhenKeyExistWithinHttpContext_ReturnsExpectedHtml()

Я настроил прибор так, как показано ниже

var fixture = new Fixture().Customize(new AutoMoqCustomization());

Тогда остановка на ViewContext:

var vc = fixture.Freeze<ViewContext>();

Я получаю следующее исключение:

Ошибка 1 Тест 'MvcDemo2.Tests.Controllers.SampleHelpersTestsAutoFixture.SampleTableHtmlHelper_WhenKeyExistWithinHttpContext_ReturnsExpectedHtml' ошибка: System.Reflection.TargetInvocationException: исключение имеет был брошен целью вызова. ---- System.NotImplementedException: метод или операция не реализованы. в System.RuntimeMethodHandle._InvokeMethodFast (IRuntimeMethodInfo метод, Object target, Object [] arguments, SignatureStruct & sig, MethodAttributes methodAttributes, RuntimeType typeOwner) в System.RuntimeMethodHandle.InvokeMethodFast (метод IRuntimeMethodInfo, Цель объекта, аргументы Object [], сигнатура сигнатуры, методAttributes methodAttributes, RuntimeType typeOwner) в System.Reflection.RuntimeMethodInfo.Invoke (Object obj, BindingFlags invokeAttr, Binder Binder, Object [] параметры, CultureInfo культура, Boolean skipVisibilityChecks) в System.Reflection.RuntimeMethodInfo.Invoke (Object obj, BindingFlags invokeAttr, Binder Binder, Object [] параметры, CultureInfo culture)
в System.Reflection.RuntimePropertyInfo.SetValue (Object obj, Object значение, BindingFlags invokeAttr, Binder Binder, Object [] index, КультураИнфо культура) на System.Reflection.RuntimePropertyInfo.SetValue (Object obj, Object значение, индекс объекта []) в Ploeh.AutoFixture.Kernel.AutoPropertiesCommand 1.Execute(T specimen, ISpecimenContext context) at Ploeh.AutoFixture.Kernel.Postprocessor 1.Create (запрос объекта, Контекст ISpecimenContext) в Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder. <> C__DisplayClass6.b__1 (ISpecimenBuilder б) в System.Linq.Enumerable.WhereSelectListIterator 2.MoveNext()<br> at System.Linq.Enumerable.WhereSelectEnumerableIterator 2.MoveNext ()
на System.Linq.Enumerable.d__a5 1.MoveNext()<br> at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable 1 источник) в Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.Create (Объект запрос, контекст ISpecimenContext) в Ploeh.AutoFixture.Kernel.RecursionGuard.Create (Запрос объекта, Контекст ISpecimenContext) в Ploeh.AutoFixture.Kernel.SpecimenContext.Resolve (запрос объекта) в Ploeh.AutoFixture.Kernel.SeedIgnoringRelay.Create (Запрос объекта, Контекст ISpecimenContext) в Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder. <> C__DisplayClass6.b__1 (ISpecimenBuilder б) в System.Linq.Enumerable.WhereSelectListIterator 2.MoveNext()<br> at System.Linq.Enumerable.WhereSelectEnumerableIterator 2.MoveNext ()
на System.Linq.Enumerable.d__a5 1.MoveNext()<br> at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable 1 источник) в Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.Create (Объект запрос, контекст ISpecimenContext) в Ploeh.AutoFixture.Kernel.Postprocessor 1.Create(Object request, ISpecimenContext context) at Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.<>c__DisplayClass6.<Create>b__1(ISpecimenBuilder b) at System.Linq.Enumerable.WhereSelectListIterator 2.MoveNext ()
в System.Linq.Enumerable.WhereSelectEnumerableIterator 2.MoveNext()<br> at System.Linq.Enumerable.<DefaultIfEmptyIterator>d__a5 1.MoveNext ()
в System.Linq.Enumerable.FirstOrDefault [TSource] (IEnumerable 1 source) at Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.Create(Object request, ISpecimenContext context) at Ploeh.AutoFixture.Kernel.RecursionGuard.Create(Object request, ISpecimenContext context) at Ploeh.AutoFixture.Kernel.SpecimenContext.Resolve(Object request) at Ploeh.AutoFixture.SpecimenFactory.CreateAnonymous[T](ISpecimenContext context, T seed) at Ploeh.AutoFixture.SpecimenFactory.CreateAnonymous[T](ISpecimenBuilderComposer composer, T seed) at Ploeh.AutoFixture.FixtureFreezer.Freeze[T](IFixture fixture, T seed)<br> at MvcDemo2.Tests.Controllers.SampleHelpersTestsAutoFixture.SampleTableHtmlHelper_WhenKeyExistWithinHttpContext_ReturnsExpectedHtml() in C:\Users\...:line 78 ----- Inner Stack Trace ----- at System.Web.HttpContextBase.get_Items() at System.Web.Mvc.ViewContext.ScopeCache.Get(IDictionary 2 scope, HttpContextBase httpContext) в System.Web.Mvc.ViewContext.SetClientValidationEnabled (логическое значение включено, Область видимости IDictionary`2, HttpContextBase httpContext) в System.Web.Mvc.ViewContext.set_ClientValidationEnabled (Boolean значение) C: \ Users ... 78

Кажется, что происходит сбой при попытке установить значение свойства ViewContext.SetClientValidationEnabled.

Я застрял на этом. Любые мысли с благодарностью.

Ответы [ 3 ]

5 голосов
/ 12 сентября 2011

Что ж, если вы рассмотрите трассировку внутреннего стека, вы заметите, что исключение выдается HttpContextBase.Items.Если бы вы взглянули на реализацию, используя инструмент отражения, вы обнаружите, что этот виртуальный метод генерирует исключение NotImplementedException - говорите о нарушении POLA.Многие веб-абстракции в BCL делают именно это, с чем действительно очень трудно иметь дело.

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

fixture.Customize<ViewContext>(c => c.OmitAutoProperties());
0 голосов
/ 05 марта 2015

Кажется, что не удается, когда он пытается установить значение свойства ViewContext.SetClientValidationEnabled.

Эта проблема была исправлена ​​для меня с помощью этого ответа , посмотрите, какон получает HtmlHelper (см. также здесь ).

0 голосов
/ 14 сентября 2011

Спасибо, Марк.Я считаю, что AutoFixture очень полезна, но когда я тестирую модуль MVC, я нахожу немного сложнее применить API.Вероятно, это потому, что я все еще плохо знаком с API.

с ...

  vc.HttpContext.Items.Add(Keys.SomeKey, "foo");

Исключение: метод или операция не реализованы.

Отражатель на HttpContextBase ...

  public virtual IDictionary Items
  {
     get
     {
         throw new NotImplementedException();
     }
  }

Так что единственныйЯ могу подумать о том, чтобы создать собственную реализацию HttpContextBase

    private class FakeHttpContext : HttpContextBase
    {
        private Dictionary<object, object> _items = new Dictionary<object, object>();
        public override IDictionary Items { get { return _items; } }
    }

. Ниже приведен запутанный бит.

   fixture.Inject<HttpContextBase>(new FakeHttpContext());
   var hc = fixture.CreateAnonymous<HttpContextBase>();

Если я поменяю местами эти две строки (что создает экземпляр anonymouseсначала, а затем внедрить поддельный экземпляр) вызывает ошибку ..

AutoFixture не удалось создать экземпляр из System.Web.HttpContextBase, скорее всего из-за отсутствия открытого конструктора.

Пока я могу создать такой тест ...

    public void SampleTableHtmlHelper_WhenKeyExistWithinHttpContext_ReturnsExpectedHtml()
    {
        //Arrange
        var fixture = new Fixture(); 
        fixture.Customize<ViewContext>(c => c.OmitAutoProperties());
        var vc = fixture.Freeze<ViewContext>();
        fixture.Inject<HttpContextBase>(new FakeHttpContext());
        var hc = fixture.CreateAnonymous<HttpContextBase>();

        vc.HttpContext = hc;
        vc.HttpContext.Items.Add(Keys.SomeKey, "foo");

        var htmlHelper = fixture.CreateAnonymous<HtmlHelper>();
        var sampleModel = fixture.CreateAnonymous<SampleModel>();

        //Act
        var result = SampleHelpers.SampleTable(htmlHelper, sampleModel, null).ToString();

        //Assert
        Assert.Equal("<table id=\"foo\"></table>", result);
    }

Также удален новый AutoMoqCustomization (), так как он, похоже, не влияет на тест.Как только я познакомлюсь с AutoFixture, я смогу найти лучшую версию.Спасибо за помощь.

...