Pregunta

La pregunta original es:Probar unidades un ayudante HTML con autofixture

No estoy seguro de volver a abrir la pregunta original; Sin embargo, desde que marcé la pregunta original como se resolvió, decidí crear una nueva. Disculpas si hiciera esto mal.

Estaba usando el enfoque sugerido de Mark, pero me quedé atascado mientras usaba la congelación.

A continuación se muestra el código fuente completo ... clase en prueba:

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
  {
  }
}

La prueba unitaria es asegurarse de que el HTML regrese como se esperaba para la clave especificada dentro de HTTPContext

public void SampleTableHtmlHelper_WhenKeyExistWithinHttpContext_ReturnsExpectedHtml()

Configuré el accesorio como se muestra a continuación

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

Luego, la congelación en ViewContext:

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

Obtengo la siguiente excepción:

Error 1 Prueba 'mvcdemo2.tests.controllers.sampleHelperstestsautofixture.sampleTableHtmlHelper_WhenkeyExistWithInHttpContext_ReturnsexpectedHtml' falló: System.Rflection.TargetInVocationException: la excepción se ha lanzado por el objetivo de una invocación. ---- System.notiMplementedException: no se implementa el método u operación. at System.RuntimeMethodHandle._InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeType typeOwner) at System.RuntimeMethodHandle.InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes , RuntimeType typeOnder) en System.Reflamection.RuntimeMethodinfo.invoke (Object OBJ, BindingFlags Invokeattr, Binder Binder, Object [] Parámetros, cultura de cultura, cultura, boolean SkipVisibilityChecks) en System.Rflection.Runtimemethodinfo.invoke (Obj, Obj, BindeflageAttr, binders Invokeats InvokeTtr, binders InvokeTr, binders InvokeRs InvokeRs InvokeTr, binders InvokeRs Invokeats Invokes , Objeto [] parámetros, cultura de cultura)
en System.Reflection.RuntimePropertyInfo.SetValue (Obj OBJ, valor de objeto, BindingFlags Invokeattr, Binder Binder, Object [] Índice, CultureInfo Culture) en System.Reflection.RuntimEpRopertyinfo.SetValue (Obj Obj, valor de objeto, objeto [] Índice) ATT ATT ATT AT AT Ploeh.autofixture.kernel.autopropertiescommand1.Execute(T specimen, ISpecimenContext context) at Ploeh.AutoFixture.Kernel.Postprocessor1.create (solicitud de objeto, contexto de ispecimencontext) en ploeh.autofixture.kernel.compositespecimenbuilder. <> C__displayclass6.b__1 (ispecimenbuilder b) en System.linq.enumerable.WhereselectItIterator2.MoveNext()
at System.Linq.Enumerable.WhereSelectEnumerableIterator
2.MoVENEXT ()
en System.linq.enumerable.d__a51.MoveNext()
at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable
1 fuente) en ploeh.autofixture.kernel.compositespecimenBuilder.create (solicitud de objeto, contexto ispecimencontext) en ploeh.autofixture.kernel.recursionguard.create (solicitud de objeto, contexto de ispecimencontext) en ploeh.autofixture.kernel.specimencontext.RraSolve (Object Solicit ) en ploeh.autofixture.kernel.seedignoringrelay.create (solicitud de objeto, contexto ispecimencontext) en ploeh.autofixture.kernel.compositespecimenBuilder. <> c__displayclass6.b__1 (ispecimenbuilder b) en el sistema.linq.enumerable.wureSelectlecterlecterlecterlecterlecterlecterlecterlecterlecterlecterlecterlecterlecterlecterlecterlecterlecterlecterleteraterateratreterateraterateraterateraterateratreterateraterateratreteratreteratreteratreteratreteratreteratreteradores2.MoveNext()
at System.Linq.Enumerable.WhereSelectEnumerableIterator
2.MoVENEXT ()
en System.linq.enumerable.d__a51.MoveNext()
at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable
1 fuente) en ploeh.autofixture.kernel.compisespecimenbuilder.create (solicitud de objeto, contexto de ispecimencontext) en ploeh.autofixture.kernel.postprocessor1.Create(Object request, ISpecimenContext context) at Ploeh.AutoFixture.Kernel.CompositeSpecimenBuilder.<>c__DisplayClass6.<Create>b__1(ISpecimenBuilder b) at System.Linq.Enumerable.WhereSelectListIterator2.MoVENEXT ()
en System.Linq.enumerable2.MoveNext()
at System.Linq.Enumerable.<DefaultIfEmptyIterator>d__a5
1.MoVENEXT ()
en System.linq.enumerable.firstordefault [tsource] (Ienumerable1 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)
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) en System.Web.MVC.ViewContext.SetClientValidAnEnlected (Boolean habilitado, Idictionary`2 scope, httpContextBase httpContext) en System.web.mvc.viewContext.set_clientvalidationSeNAned (BooleLean valor)

Parece que falla cuando intenta establecer el valor de la propiedad ViewContext.SetClientValidAnEnabled.

Estoy atrapado en esto. Cualquier pensamiento muy apreciado.

¿Fue útil?

Solución

Bueno, si considera el rastro de la pila interior, notará que la excepción está siendo lanzada por HttpContextBase.Items. Si observara la implementación utilizando una herramienta de reflexión, encontraría que este método virtual arroja una NotimplementEdException: hable sobre una violación de pola. Muchas de las abstracciones web en el BCL hacen exactamente eso, lo cual es realmente muy doloroso de tratar.

No estoy seguro de que te ayude más adelante, pero puedes superar este problema en particular apagando las autoproperties para la clase ViewContext como esta:

fixture.Customize<ViewContext>(c => c.OmitAutoProperties());

Otros consejos

Gracias Mark. Encuentro que la autofixture es muy útil, pero cuando pruebo unidades de prueba MVC, encuentro un poco más complicado para aplicar la API. Probablemente sea porque todavía soy nuevo en la API.

Con….

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

Lo anterior funciona bien, pero como sospecha que falla nuevamente cuando intento agregar elementos a

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

Excepto: el método u operación no se implementa.

El reflector en httpContextBase ...

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

Entonces, la única forma en que puedo pensar es crear mi propia implementación de httpcontextbase

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

Entonces a continuación se encuentra el bit confuso.

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

Si intercambio estas dos líneas (que crean primero la instancia de Anonymouse y luego inyectan la instancia falsa) provoca el error.

La autofixture no pudo crear una instancia de System.Web.httpContextBase, muy probablemente porque no tiene un constructor público.

Hasta ahora puedo llegar a una prueba como esta ...

    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);
    }

También se eliminó la nueva AutoCustomization (), ya que parece no tener ningún efecto en la prueba. Una vez que me familiarice con la autofixture, podría encontrar una mejor versión. Gracias por la ayuda.

Parece que falla cuando intenta establecer el valor de la propiedad ViewContext.SetClientValidationEnabled.

Ese problema fue solucionado para mí por esta respuesta, mira cómo obtiene un htmlhelper (ver también aquí).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top