Domanda

La domanda originale è:Test dell'unità un aiuto HTML con autofixture

Non sono sicuro che dovrei riaprire la domanda originale; Tuttavia da quando ho segnato la domanda originale come risolto, ho deciso di crearne una nuova. Mi scuso se ho fatto questo male.

Stavo usando l'approccio suggerito di Mark ma mi sono bloccato mentre usavo il congelamento.

Di seguito è riportato il codice sorgente completo ... Classe in Test:

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

Il test dell'unità è garantire che l'HTML restituisca come previsto per la chiave specificata all'interno di HTTPContext

public void SampleTableHtmlHelper_WhenKeyExistWithinHttpContext_ReturnsExpectedHtml()

Ho configurato il dispositivo come sotto

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

Quindi il congelamento su ViewContext:

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

Ottengo l'eccezione seguente:

Errore 1 test 'mvcdemo2.tests.controllers.samplehelperstsautofixture.sampletablehtmlhelper_whenkeyexistwithinhttcontext_returnsexpectedhtml' fallito: system.reflection.targetinvocationException: l'eccezione è stata lanciata dal bersaglio di un invoca. ---- System.NotImplementEdException: il metodo o l'operazione non è implementato. su system.runtimeMethodHandle._invokemethodfast (metodo IruntimeMethodInfo, Object Target, Object [] Argomenti, SignatureStrUct & Sig, MethodoTributes MethodTribute , RuntimeType typewer) su system.reflection.runtimemethodinfo.invoke (oggetto obj, bindflags invokeattr, legante legante, oggetto [] parametri, cultura cultura , Object [] Parametri, CultureInfo Culture)
su system.reflection.RuntimePropertyInfo.setValue (oggetto OBJ, valore oggetto, BindingFlags Invokeattr, Binder Binder, Indice Object [], Culture CultureInfo) su System.Reflection.RuntimePropertyInfo.setValue (oggetto OBJ, valore oggetto, indice oggetto [] a Ploeh.autofixture.kernel.autopropertiescommand1.Execute(T specimen, ISpecimenContext context) at Ploeh.AutoFixture.Kernel.Postprocessor1.Create (richiesta oggetto, contesto di ispecimenContext) su ploeh.autofixture.kernel.compositeSpecimenBuilder. <> C__displayclass6.b__1 (ispecimenbuilder b) su system.linq.enumerable.whereSelectListiterator2.MoveNext()
at System.Linq.Enumerable.WhereSelectEnumerableIterator
2.MoveNext ()
su system.linq.enumerable.d__a51.MoveNext()
at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable
1 Fonte) su ploeh.autofixture.kernel.comPositeSpecimenBuilder.Create (richiesta oggetto, contesto di ispecimenContext) su ploeh.autofiture.kernel.recursionGuard.create (richiesta oggetto, ispecimenText contesto) su ploeh.autofixture.kernel.specimenTexte. ) su ploeh.autofixture.kernel.seedignoringrelay.create (richiesta oggetto, contesto di ispecimenContext) su ploeh.autofixture.kernel.comPositeSpeSpecimenBuilder. <> C__displayclass6.b__1 (ispecimenbuilder b) at system.lin -llinq.eenumerable.whereSeleTiterator.2.MoveNext()
at System.Linq.Enumerable.WhereSelectEnumerableIterator
2.MoveNext ()
su system.linq.enumerable.d__a51.MoveNext()
at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable
1 Fonte) su ploeh.autofixture.kernel.comPositeSpecimenBuilder.Create (richiesta oggetto, contesto di ispecimenContext) su 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 ()
su system.linq.enumerable.whereselectenumerableiterator2.MoveNext()
at System.Linq.Enumerable.<DefaultIfEmptyIterator>d__a5
1.MoveNext ()
all'indirizzo system.linq.enumerable.firsterGefault [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 Ambito, HttpContextBase HttpContext) su System.Web.MVC.ViewContext.SetClientValidationAbled (abilitato booleano, Ambito Idictionary`2, ambito di Ampe, HttpContextBase ... 78

Sembra che fallisca quando prova a impostare il valore di Proprietà ViewContext.SetClientValidationAbled.

Sono bloccato su questo. Qualsiasi pensiero molto apprezzato.

È stato utile?

Soluzione

Bene, se consideri la traccia dello stack interiore, noterai che l'eccezione viene lanciata HttpContextBase.Items. Se dovessi esaminare l'implementazione usando uno strumento di riflessione, scopriresti che questo metodo virtuale lancia un ExplementException - parla di una violazione di pola. Molte astrazioni web nel BCL fanno esattamente questo, il che è davvero molto doloroso da affrontare.

Non sono sicuro che ti aiuterà ulteriormente, ma puoi superare questo particolare problema disattivando le autopropertie per la classe ViewContext come questa:

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

Altri suggerimenti

Grazie Mark. Trovo che l'autofixture sia molto utile ma quando ho unità test mvc, trovo un po 'più complicato per applicare l'API. Probabilmente è perché sono ancora nuovo nell'API.

Insieme a….

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

Quanto sopra funziona bene, ma quando sospettavi fallisce di nuovo quando provo ad aggiungere oggetti a

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

Transortiion: il metodo o l'operazione non è implementato.

Il riflettore su HttpContextBase ...

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

Quindi l'unico modo per pensare è creare la mia implementazione di HttpContextBase

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

Allora sotto c'è il bit confuso ..

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

Se scambio queste due righe (che crea prima l'istanza Anonyuse e poi inietta l'istanza falsa) provoca l'errore.

AutoFixture non è stato in grado di creare un'istanza da System.Web.httpContextBase, molto probabilmente perché non ha costruttori pubblici.

Finora posso trovare un test come questo ...

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

Inoltre, ha rimosso il nuovo AutomoqCustomization () in quanto sembra non avere alcun effetto sul test. Una volta che avrò più familiarità con AutoFixture, potrei essere in grado di trovare una versione migliore. Grazie per l'aiuto.

Sembra che non riesca a non rientrare quando prova a impostare il valore della proprietà ViewContext.SetClientValidationEnabled.

Quel problema è stato risolto per me da questa risposta, vedi come ottiene un htmlhelper (vedi anche qui).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top