Metodo Fixture.CreateAnonymous uccide processo di test runner con un errore (AutoFixture) quando si utilizza AutoMoq per creare un controller

StackOverflow https://stackoverflow.com/questions/3514102

Domanda

Sto cercando di utilizzare l'AutoMoqCustomization con AutoFixture per creare un MVC2 controller ASP.NET in un test di unità attraverso il metodo Fixture.CreateAnonymous. Ho provato sia xUnit sotto TestDriven.NET, la GUI di prova xUnit e in MSTest e tutti hanno lo stesso risultato: un massiccio fallimento del processo di esecuzione del test. In Windows 7 x64 se quello che conta.

Per riprodurre, è sufficiente creare un nuovo progetto ASP.NET MVC2, aggiungere i riferimenti a AutoFixture, AutoMoq e Moq (3.1, secondo la fonte AutoMoq) e provare la sotto (repro VS2010 MVC2 collegamento al progetto di seguito):

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

Nel MSTest l'errore legge:

  

Il runtime è verificato un errore fatale. L'indirizzo dell'errore era a 0x6465f370, sul filetto 0x2684. Il codice di errore è 0xc0000005. Questo errore può essere un bug nel CLR o nelle porzioni non sicuri o non verificabili di codice utente. Le fonti comuni di questo bug sono errori di marshalling utente per COM-interoperabilità o PInvoke, che potrebbe danneggiare lo stack.

AfWithMvc Repro progetto (da SkyDrive)

È stato utile?

Soluzione

Soluzione suggerita

Per iniziare con una possibile soluzione, questo dovrebbe fermare il crash:

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

Spiegazione

E ora per la spiegazione:

Questo errore di prova è causato da AutoFixture di AutoProperties funzione cercando di assegnare un valore a HomeController.ViewData.ModelMetaData. La classe ModelMetaData ha questo costruttore:

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

Il colpevole qui è il parametro modelAccessor. Per colmare questa AutoFixture proprietà (piuttosto stupidamente) riflette sul tipo e trova questo singolo costruttore:

public Func(object @object, IntPtr method)

Scavando ulteriormente, il primo costruttore AutoFixture IntPtr in grado di soddisfare è questa:

public unsafe IntPtr(int value)

Per impostazione predefinita, Int32 istanze vengono create da una sequenza crescente deterministica , quindi value in questo caso sarà probabilmente 1 o 2 o un piccolo numero intero simile. In altre parole, ora abbiamo un molto valida puntatore non sicuri sulle nostre mani, e questo sta rendendo l'incidente processo.

Ora, in circostanze normali dovremmo essere in grado di risolvere questo problema registrando un Func<object> con il fissaggio e tutto dovrebbe essere Dandy:

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

Tuttavia, ho provato questo con il vostro Repro e anche se il processo non si blocca più nello stesso modo, le corse di prova per un tempo molto lungo e, infine, si blocca con un OutOfMemoryException.

Non so cosa ASP.NET MVC fa con Func<object>, ma a quanto pare lo usa abbastanza heaviliy.

I resti questione se si tratta di un bug in AutoFixture?

Credo che non lo è. Mentre è sicuramente meno che ideale, AutoFixture non funcs trattare o azioni in modo diverso rispetto ad altri tipi, che è il motivo per cui noi vediamo questo comportamento.

Questo comportamento particolare potrebbe essere affrontato con l'aggiunta di un supporto specifico per Func<TResult>, ma di rimanere coerente dovrebbe anche avere il supporto per Func<T, TResult>, Func<T1, T2, TResult>, ecc AFAIR in .NET 4 ci sono molto di questi tipi delegato (anche di azione, ecc), in modo che significherebbe l'aggiunta di supporto per tutta una serie di tipi.

Ma allora che dire di tutti gli altri tipi che accettano un IntPtr nella loro costruttore? AutoFixture non può assolutamente sapere su di loro tutto, quindi questo non sembra una direzione valida.

Tuttavia, ciò che potrebbe avere è un guardia che gli impedisce di tentare per creare istanze IntPtr in primo luogo . Questo sarà molto probabilmente aggiunto prima del 2.0 RTW.

Grazie per aver segnalato questo.

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