2011-11-02 14 views
14

He leído muchos otros QA sobre este tema y todavía no puedo encontrar la solución a mi problema, entonces he decidido exponer mi caso.Moq.Mock <Expression <Func<T,bool> >>() - cómo configurar expresiones en un Mock usando Moq

tengo esta interfaz

public interface IRepository<T> where T : class, IEntity 
{ 
    IQueryable<T> Find(Expression<Func<T, bool>> predicate); 
    T FindIncluding(int id, params Expression<Func<T, object>>[] includeProperties); 
} 

Y esta es la estructura básica del método que contiene la maqueta que me gustaría configuración

public PeopleController CreatePeopleController() 
{ 
    var mockUnitofWork = new Mock<IUnitOfWork>(); 
    var mockPeopleRepository = new Mock<IRepository<Person>>(); 

    mockPeopleRepository.Setup(r=>r.Find().Returns(new Person(){}); 
    mockUnitofWork.Setup(p => p.People).Returns(mockPeopleRepository.Object); 
    return new PeopleController(mockUnitofWork.Object); 
} 

que han estado tratando de instalar la maqueta usando de esta manera:

public PeopleController CreatePeopleController() 
{ 
    var mockUnitofWork = new Mock<IUnitOfWork>(); 
    var mockPeopleRepository = new Mock<IRepository<Person>>(); 

    mockPeopleRepository.Setup(r=>r.Find(It.isAny<Expression<Func<Person,bool>>>()).Single()).Returns(new Person(){}); 
    mockUnitofWork.Setup(p => p.People).Returns(mockPeopleRepository.Object); 
    return new PeopleController(mockUnitofWork.Object); 
} 

Pero el sistema siempre arroja la misma excepción "System.NotSup portedException: Expresión hace referencia a un método que no pertenece al objeto burlado .... "

También me gustaría añadir que estoy usando MSTest y Moq

Sé que configurar una expresión usando Mock no es fácil y no recomendado, pero es muy importante para mí porque "Buscar" es un método que uso mucho en mi aplicación

Respuesta

19

El problema es que está intentando configurar el método de extensión Single() como parte de tu burla La llamada de configuración necesita tener el resultado de su método, no el resultado de su método con algún método de extensión aplicado posteriormente. Me gustaría probar este:

[TestMethod] 
    public void MyTestMethod() 
    { 
     var myMock = new Mock<IRepository<Person>>(); 
     myMock.Setup(r => r.Find(It.IsAny<Expression<Func<Person, bool>>>())).Returns(new List<Person>() { new Person() }.AsQueryable()); 

     Assert.IsTrue(true); 
    } 

Aquí, sólo estás apagando el método Find() con la configuración, y haciendo todas las otras cosas en las devoluciones() cláusula. Sugeriría ese enfoque en general. El programa de instalación debe reflejar exactamente el elemento que se burló, y usted puede hacer un montón de magia negra para la llamada de Retorno() (o Tira() o lo que sea) para que haga lo que quiera.

(Cuando me encontré con ese código en VS, pasó, por lo que no fue una excepción)

+0

Erik acaba de implementar la solución y su trabajo .. Gracias por su ¡¡¡ayuda!!! :) – gustavotroconis

+0

Me alegro de que haya ayudado. :) –

+0

@gustavotroconis si esta respuesta resolvió su problema, puede aceptarlo haciendo clic en la marca de verificación junto a él. A medida que haga más preguntas, aparecerá un "aceptar%" debajo de su avatar y un% más animará a otros a responder sus preguntas. –

4

El uso de It.IsAny<> Moq sin .CallBack te obliga a escribir código que no está cubierto por su prueba. En cambio, permite que cualquier consulta/expresión pase, haciendo que tu simulacro sea básicamente inútil desde una perspectiva de prueba de unidad.

La solución: o necesita utilizar una Devolución de llamada para probar la expresión O necesita restringir su simulacro mejor. De cualquier manera es complicado y difícil. He tratado este tema mientras he estado practicando TDD. Finalmente armé una clase de ayudante para hacer esto mucho más expresivo y menos desordenado. Aquí está el resultado final (adaptado a su ejemplo):

mockPeopleRepository 
    .Setup(x => x.Find(ThatHas.AnExpressionFor<Person>() 
    .ThatMatches(correctPerson) 
    .And().ThatDoesNotMatch(deletedPerson) 
    .Build())) 
    .Returns(_expectedListOfPeople); 

Aquí está el artículo del blog que habla de él y le da al código fuente: http://awkwardcoder.com/2013/04/24/constraining-mocks-with-expression-arguments/

Cuestiones relacionadas