2011-11-02 22 views
14

Ho letto molti altri QA su questo argomento e non riesco ancora a trovare la soluzione al mio problema, quindi ho deciso di esporre il mio caso.Moq.Mock <Expression <Func<T,bool> >>() - come impostare le espressioni in un Mock usando Moq

ho questa interfaccia

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

E questa è la struttura di base del metodo che contiene la Falsa che vorrei per impostare

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

Ho cercato di impostare il Mock utilizzando in questo modo:

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

Ma il sistema genera sempre la stessa eccezione "System.NotSup portedException: espressione fa riferimento a un metodo che non appartiene all'oggetto deriso .... "

Inoltre vorrei aggiungere che sto usando MSTest e Moq

So che l'installazione di un Mock utilizzando Expression non è facile e non consigliato, ma è molto importante per me perché "Trova" è un metodo che uso molto nella mia app

risposta

19

Il problema è che stai provando a impostare il metodo di estensione Single() come parte di il tuo beffardo. La chiamata all'impostazione deve avere il risultato del tuo metodo, non il risultato del tuo metodo con qualche metodo di estensione successivamente applicato ad esso. Mi piacerebbe provare questo:

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

Qui, si sta solo spegnendo il metodo find() con l'installazione, e fare tutte le altre cose nelle Returns() clausola. Suggerirei questo approccio in generale. L'installazione dovrebbe rispecchiare esattamente il tuo oggetto deriso e puoi fare un po 'di magia nera per la chiamata Returns() (o Throws() o qualsiasi altra cosa) per farlo fare ciò che vuoi.

(Quando ho fatto funzionare quel codice in VS, passò, così non è stato un'eccezione)

+0

Erik basta implementare la soluzione e il suo lavoro .. Grazie per la vostra Aiuto!!! :) – gustavotroconis

+0

Felice di averlo aiutato. :) –

+0

@gustavotroconis se questa risposta ha risolto il tuo problema, puoi accettarlo facendo clic sul segno di spunta accanto ad esso. Mentre fai altre domande, un "accetta%" apparirà sotto il tuo avatar, e una percentuale più alta incoraggia gli altri a rispondere alle tue domande. –

4

Usando del It.IsAny<> Moq senza .CallBack forze di scrivere codice che non è coperto dalla vostra prova. Invece, permette a qualsiasi query/espressione di passare attraverso, rendendo il tuo finto praticamente inutile da una prospettiva di testing unitario.

La soluzione: è necessario utilizzare una richiamata per testare l'espressione OPPURE è necessario limitare meglio la simulazione. In entrambi i casi è disordinato e difficile. Ho affrontato questo problema fino a quando ho praticato TDD. Alla fine ho riunito una classe di aiuto per renderla molto più espressiva e meno disordinata. Ecco il risultato finale (adattato per il tuo esempio):

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

Ecco l'articolo blog che parla e dà il codice sorgente: http://awkwardcoder.com/2013/04/24/constraining-mocks-with-expression-arguments/

Problemi correlati