2011-09-26 10 views
7

Estoy intentando escribir una prueba unitaria de una implementación de repositorio. El repositorio utiliza RavenDB como una base de datos. Para las pruebas unitarias, me gustaría burlarme de las piezas de RavenDB. Para crear los simulacros (falsificaciones) estoy usando FakeItEasy. Pensé que no habría ningún problema con la burla/falsificación ya que se accede a la API RavenDB a través de las interfaces.Fingir/burlarse de una interfaz da error "no constructor por defecto", ¿cómo puede ser eso?

Sin embargo, tengo un problema al intentar crear una instancia de un simulacro específico. Las partes pertinentes de mi código de prueba de unidad se ve así:

[Fact] 
public void Test() { 
    UserDocument doc = ...; 
    IQueryable<UserDocument> where = A.Fake<IQueryable<UserDocument>>(); 
    A.CallTo(() => where.First()).Returns(doc); 
    IRavenQueryable<UserDocument> query = A.Fake<IRavenQueryable<UserDocument>>(); 
    IDocumentSession session = A.Fake<IDocumentSession>(); 
    A.CallTo(() => session.Query<UserDocument>()).Returns(query); 
    IDocumentStore store = A.Fake<IDocumentStore>(); 
    A.CallTo(() => store.OpenSession()).Returns(session); 
    . 
    . 
    . 
} 

Cuando una instancia de la falsa IRavenQueryable consigo una excepción. Este es el registro del corredor Xunit.net:

UnitTest.Test : FakeItEasy.Core.FakeCreationException : 
    Failed to create fake of type "System.Linq.IQueryable`1[UserDocument]". 

    Below is a list of reasons for failure per attempted constructor: 
    No constructor arguments failed: 
     No default constructor was found on the type System.Linq.IQueryable`1[UserDocument]. 


Stack Trace: 
    vid FakeItEasy.Core.DefaultExceptionThrower.ThrowFailedToGenerateProxyWithResolvedConstructors(Type typeOfFake, String reasonForFailureOfUnspecifiedConstructor, IEnumerable`1 resolvedConstructors) 
    vid FakeItEasy.Creation.FakeObjectCreator.TryCreateFakeWithDummyArgumentsForConstructor(Type typeOfFake, FakeOptions fakeOptions, IDummyValueCreationSession session, String failReasonForDefaultConstructor, Boolean throwOnFailure) 
    vid FakeItEasy.Creation.FakeObjectCreator.CreateFake(Type typeOfFake, FakeOptions fakeOptions, IDummyValueCreationSession session, Boolean throwOnFailure) 
    vid FakeItEasy.Creation.DefaultFakeAndDummyManager.CreateFake(Type typeOfFake, FakeOptions options) 
    vid FakeItEasy.Creation.DefaultFakeCreatorFacade.CreateFake[T](Action`1 options) 

El "ningún constructor por defecto encontrado" No tiene ningún sentido ya que lo que estoy tratando de falsificar es una interfaz. ¿Alguien tiene alguna sugerencia de cuál podría ser el problema?

+0

Acabo de notar que su mensaje de excepción menciona ** "System.Linq.IQueryable \' 1 [UserDocument] "**, no específicamente' IRavenQueryable '. ¿Está seguro de que la excepción no se produce al crear la instancia de 'IQueryable '? – Rob

+0

Sí, estoy seguro. Sin embargo, IRavenQueryable amplía la interfaz IQueryable , así que supongo que FakeItEasy falla al intentar falsificar la parte IQueryable si IRavenQueryable ... o algo así. –

+0

¿El público de UserDocument es público? –

Respuesta

6

Tiene razón en que el mensaje de excepción no tiene ningún sentido, esto es un error. Sería genial si pudiera suministrar una solución VS que reproduzca el error y presente un problema aquí: https://github.com/patrik-hagne/FakeItEasy/

El error se debe a que se utiliza el mensaje de excepción incorrecto, sin embargo debe haber algo incorrecto que haga que la creación falsa ir mal. ¿Es público el tipo "UserDocument"? Si es interno y le ha dado acceso a su proyecto de prueba a través del uso de InternalsVisibleToAttribute, también debe darle acceso a la biblioteca generadora de proxy: https://github.com/FakeItEasy/FakeItEasy/wiki/How-to-fake-internal-(Friend-in-VB)-types.

2

¿Tiene la interfaz IRavenQueryable<T> un where T : new()type constraint?

Si es así, y UserDocument no proporciona un ctor sin parámetros, esto podría estar causando su problema.

+0

Por lo que puedo decir, no existe tal restricción en IRavenQueryable . Incluso si existe, UserDocument tiene un constructor sin parámetros. –

2

Acabo de toparme con esto, pero mi problema no estaba relacionado con los tipos internos. Mi problema era con el ensamblado que contenía el tipo que no estaba en la carpeta bin del proyecto de prueba de la unidad.

Parece que FakeItEasy arroja este error cuando no puede resolver un tipo que necesita fingir. (Esto tiene sentido por qué un tipo interno en otro ensamblado causaría el mismo error.)

Entonces, tenía Project Foo, al que hace referencia la Barra de proyectos. Project Bar tenía una interfaz pública que hacía referencia a un tipo público de Project Foo. Project Bar.Tests tiene una referencia a Project Bar, pero no a Project Foo. Cuando construyo Bar.Test, Bar.dll se coloca en la carpeta bin, pero Foo.dll no. Cuando FakeItEasy intenta falsificar mi interfaz, no puede resolver el tipo que reside en Foo.dll.

Agregando una referencia a Project Foo en mi barra. El proyecto de pruebas aseguró que Foo.dll se acerca y está allí para FakeItEasy e hizo desaparecer este error.

Entonces ...

En su caso, podría ser que su montaje RavenDB (que supongo contiene UserDocument) sólo se hace referencia a su proyecto actual y no está siendo copiado a su unidad de salida de la prueba de generación.

+0

Trataré de reproducir esto y obtener una solución lo más pronto posible. –

1

Sé que es una publicación anterior, pero me encontré con el mismo problema. Lo que me pareció que era el problema era un tipo de devolución de uno de los métodos declarados en la interfaz que intentaba simular. Este método devolvía un objeto de una cierta clase, y esta clase no tenía un constructor predeterminado con el que FakeItEasy podría funcionar. Si alguien más obtiene este error, intente comprobar los objetos que devuelve su interfaz, y si las clases correspondientes tienen los constructores por defecto.

+0

¿Cómo resolverías esto? ¿Es posible falsificar el método que devuelve un objeto que no tiene un constructor predeterminado? –

Cuestiones relacionadas