2010-05-01 4 views
27

저장소 인터페이스를 조롱하고 있으며 표현식을 사용하고 객체를 반환하는 메소드를 설정하는 방법을 모르십니까? 된 IQueryable 이미 설치와Moq.Mock <T> - 표현식을 사용하는 메소드를 설정하는 방법

public interface IReadOnlyRepository : IDisposable 
{ 
    IQueryable<T> All<T>() where T : class; 
    T Single<T>(Expression<Func<T, bool>> expression) where T : class; 
} 

시험 만 설치하는 방법 모르는 T 단일 : 나는

인터페이스 MOQ와 NUnit를 사용하고

private Moq.Mock<IReadOnlyRepository> _mockRepos; 
private AdminController _controller; 
[SetUp] 
public void SetUp() 
{ 
    var allPages = new List<Page>(); 
    for (var i = 0; i < 10; i++) 
    { 
     allPages.Add(new Page { Id = i, Title = "Page Title " + i, Slug = "Page-Title-" + i, Content = "Page " + i + " on page content." }); 
    } 
    _mockRepos = new Moq.Mock<IReadOnlyRepository>(); 
    _mockRepos.Setup(x => x.All<Page>()).Returns(allPages.AsQueryable()); 
    //Not sure what to do here??? 
    _mockRepos.Setup(x => x.Single<Page>() 
    //---- 
    _controller = new AdminController(_mockRepos.Object); 
} 

답변

37

당신처럼 설정할 수 있습니다 이 :

_mockRepos.Setup(x => x.Single<Page>(It.IsAny<Expression<Func<Page, bool>>>()))//.Returns etc...; 

그러나 당신은 Moq의 단점 중 하나에 맞서고 있습니다. It.IsAny을 사용하는 대신 실제 표현식을 사용하고 싶지만 Moq은 특정 표현식을 사용하는 표현식을 설정하는 방법을 지원하지 않습니다. 구현하기가 어렵습니다. 어려움은 두 표현식이 동등한 지 알아 내야하는 데서 오는 것입니다.

따라서 테스트에서는 Expression<Func<Page,bool>> 번으로 전달할 수 있으며, 모의 설정을 반환해도 되돌릴 수 있습니다. 시험의 가치는 약간 희석됩니다.

+1

답장을 보내 주셔서 감사합니다. 위 코드에서 오류가 발생합니다. 오류 인수 '1': 'System.Linq.Expressions.Expression '메서드 그룹 '을 변환 할 수 없습니다. > – Paul

+0

@Paul : 죄송합니다. 나는'()'을 삭제했습니다. 최신 버전을 사용해보십시오. 그러면 제대로 작동합니다. –

+0

답장을 보내 주셔서 감사합니다. 그 말은 당신이 언급 한 것처럼 이상적이지는 않지만 작동합니다! 다시 한번 감사드립니다. – Paul

6

.Returns 호출에서 allPages 변수에 대해 식의 결과를 반환하도록하십시오. 사용

_mockRepos.Setup(x => x.Single<Page>(It.IsAny<Expression<Func<Page, bool>>>())) 
    .Returns((Expression<Func<Page, bool>> predicate) => allPages.Where(predicate)); 
1

MOQ의 It.IsAny<> 당신이 테스트에 포함되지 것 코드를 작성하는 .CallBack 힘없이. 대신 모든 쿼리/표현식을 통과시킬 수 있으므로 모의 테스트는 기본적으로 쓸모 없게됩니다.

해결 방법 : 표현식을 테스트하기 위해 콜백을 사용해야하거나 모의 (mock)을 더 잘 적용해야합니다. 어느 쪽이든 지저분하고 어렵다. 나는 TDD를 연습하고있는 한이 문제를 다뤘다. 나는 마침내 도우미 수업을 함께 던져서 표현력이 뛰어나고 덜 지저분 해졌습니다. http://awkwardcoder.com/2013/04/24/constraining-mocks-with-expression-arguments/

+0

매우 유용하고 큰 기여. – Paul

4

내가 It.Is<T>이 이상 It.IsAny<T> 대신에 사용하는 것을 발견했다 : 여기

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

그것에 대해 이야기하고 소스 코드를 제공하는 블로그 기사입니다 : 여기에 하나의 가능한 최종 결과의 예 정확한 결과.

Page expectedPage = new Page {Id = 12, Title = "Some Title"}; 
_mockRepos.Setup(x => x.Single<Page>(It.Is<Expression<Func<Page, bool>>>(u => u.Compile().Invoke(expectedPage)))) 
         .Returns(() => expectedPage); 
관련 문제