2011-11-02 29 views
14

Tôi đã đọc rất nhiều câu hỏi khác về chủ đề này và tôi vẫn không thể tìm ra giải pháp cho vấn đề của mình, vì vậy tôi đã quyết định để lộ trường hợp của tôi.Moq.Mock <Expression <Func<T,bool> >>() - cách thiết lập biểu thức thành mô hình bằng cách sử dụng Moq

Tôi có giao diện này

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

Và đây là cấu trúc cơ bản của phương pháp có chứa các Mock mà tôi muốn thiết lập

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

Tôi đã cố gắng để thiết lập các Mock sử dụng theo cách này:

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

Nhưng hệ thống luôn ném cùng ngoại lệ "System.NotSup portedException: Biểu hiện tham chiếu một phương pháp mà không thuộc về các đối tượng chế giễu .... "

Ngoài ra tôi muốn thêm rằng tôi đang sử dụng MSTest và Moq

Tôi biết rằng thiết lập một Mock sử dụng biểu thức không phải là dễ dàng và không được đề xuất, nhưng điều này rất quan trọng đối với tôi bởi vì "Tìm" là một phương pháp mà tôi sử dụng rất nhiều trong ứng dụng của tôi

Trả lời

19

Vấn đề là bạn đang cố gắng thiết lập phương thức mở rộng Đơn() là một phần của sự chế giễu của bạn. Cuộc gọi thiết lập cần phải có kết quả của phương thức của bạn - không phải là kết quả của phương pháp của bạn với một số phương pháp mở rộng sau đó được áp dụng cho phương thức đó. Tôi sẽ thử điều này:

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

Ở đây, bạn chỉ cần đặt phương thức Find() với tất cả các thứ khác trong mệnh đề Returns(). Tôi đề nghị cách tiếp cận nói chung. Thiết lập sẽ phản chiếu chính xác mục được chế nhạo của bạn và bạn có thể thực hiện một loạt phép màu đen cho cuộc gọi Returns() (hoặc Ném() hoặc bất kỳ) để làm cho nó làm những gì bạn muốn.

(Khi tôi chạy mã trong VS, nó trôi qua, vì vậy nó không được ném một ngoại lệ)

+0

Erik chỉ thực hiện giải pháp của bạn và công việc của mình .. Cảm ơn bạn Cứu giúp!!! :) – gustavotroconis

+0

Vui vì nó đã giúp. :) –

+0

@gustavotroconis nếu câu trả lời này giải quyết được vấn đề của bạn, bạn có thể chấp nhận nó bằng cách nhấp vào dấu kiểm bên cạnh nó. Khi bạn đặt thêm câu hỏi, "chấp nhận%" sẽ xuất hiện bên dưới hình đại diện của bạn và% cao hơn khuyến khích người khác trả lời câu hỏi của bạn. –

4

Sử dụng Moq của It.IsAny<> mà không có một .CallBack buộc bạn phải viết code mà không được diễn tả bởi thử nghiệm của bạn. Thay vào đó, nó cho phép bất kỳ truy vấn/biểu thức nào đi qua, khiến cho giả của bạn về cơ bản vô dụng từ một góc nhìn thử nghiệm đơn vị.

Giải pháp: Bạn cần sử dụng Gọi lại để kiểm tra biểu thức HOẶC bạn cần hạn chế mô hình của mình tốt hơn. Dù bằng cách nào là lộn xộn và khó khăn. Tôi đã giải quyết vấn đề này miễn là tôi đã thực hành TDD. Cuối cùng tôi đã cùng nhau học một lớp trợ giúp để làm cho điều này trở nên biểu cảm hơn và ít lộn xộn hơn. Dưới đây là kết quả cuối cùng (phù hợp với ví dụ của bạn):

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

Dưới đây là các bài viết blog nói về nó và cung cấp cho các mã nguồn: http://awkwardcoder.com/2013/04/24/constraining-mocks-with-expression-arguments/

Các vấn đề liên quan