Moq: Thiết lập không hợp lệ trên thành viên không thể ghi đè: x => x.GetByTitle (“asdf”)


111

Không chắc tôi có thể khắc phục sự cố này bằng cách nào, đang cố gắng thực hiện kiểm tra đơn vị trên phương pháp "GetByTitle"

Đây là định nghĩa của tôi:

public class ArticleDAO :  GenericNHibernateDAO(IArticle, int>, IArticleDAO
{
    public IArticle GetByTitle(string title)
    {
        IQuery query = Session.CreateQuery("...")
        return query.UniqueResult<IArticle>();
    }
}

public interface IArticleDAO
{
    IArticle GetByTitle(string title);
}

kiểm tra đơn vị:

[Test]
public void can_load_by_title()
{
    _mockDaoFactory.Setup(x => x.GetArticleDao())
                                .Returns(_mockArticleDao.Object);
    _mockArticleDao.Setup(x => x.GetByTitle("some title"))
                                .Returns(article1.Object);

    _articleManager.LoadArticle("some title");

    Assert.IsNotNull(_articleManager.Article);
}

Chạy thử nghiệm cho tôi lỗi:

System.ArgumentException: Invalid setup on a non-overridable member:
x => x.GetByTitle("some title")

Cập nhật

Tôi [Setup]trông giống như:

[Setup]
public void SetUp()
{
     _mockDaoFactory = new Mock<IDaoFactory>();
     _mockArticleDao = new Mock<ArticleDao>();

     _articleManager = new ArticleManager(_mockDaoFactory.Object);    
}

2
Bạn có khởi tạo _mockDaoFactory_mockArticleDaoở đâu đó không? Bạn có chế nhạo lớp học hay giao diện không
Tomas Aschan

Có, tôi đã chế nhạo daofactory và mockarticleDao trong [Thiết lập] bằng Giao diện. DAO đã được thực hiện bằng cách sử dụng lớp.
mrblah 25/12/09

@tomas Tôi đã cập nhật câu hỏi của mình bằng mã thiết lập.
mrblah

2
Như bạn có thể thấy trong câu trả lời của tôi, bạn cần phải mô phỏng giao diện (đó là những gì tôi đề xuất) hoặc đánh dấu GetByTitlephương pháp virtual.
Tomas Aschan

Có vẻ như dòng đầu tiên trong thử nghiệm của bạn có thể được chuyển sang quy trình thiết lập ...?
Tomas Aschan 25/12/09

Câu trả lời:


154

Để kiểm soát hành vi của một đối tượng giả (ít nhất là trong Moq), bạn cần phải giả một giao diện hoặc đảm bảo rằng hành vi bạn đang cố gắng kiểm soát được đánh dấu là ảo. Trong nhận xét của bạn, tôi hiểu điều đó vì vậy việc khởi tạo _mockArticleDaođược thực hiện như sau:

_mockArticleDao = new Mock<ArticleDAO>();

Nếu bạn muốn giữ nó như vậy, bạn cần phải đánh dấu GetArticlephương pháp virtual:

public class ArticleDAO :  GenericNHibernateDAO(IArticle, int>, IArticleDAO
{
    public virtual IArticle GetByTitle(string title)
    {
        // ...
    }
}

Nếu không (và đây là những gì tôi đề xuất), hãy mô phỏng giao diện thay thế.

_mockArticleDao = new Mock<IArticleDAO>();

nhưng vì ArticleDAO kế thừa từ Generic ...., nếu tôi mô phỏng giao diện các phương thức trong GenericNhibern. sẽ không có sẵn?
mrblah

bởi vì lệnh gọi đến GetArticleDAO từ nhà máy trả về ArticleDAO không phải IArticleDAO, b / c articleDAO cũng liên kết với một lớp trừu tượng có nội dung nhibernate trong đó.
mrblah

2
Nếu bạn không thể giả lập giao diện, thì bạn có thể đang thử nghiệm sai ... nhưng vẫn còn, đánh dấu phương pháp ảo sẽ giải quyết được vấn đề.
Tomas Aschan

+1 Tomas, tôi cần đưa một tham số vào ctor, do đó, trong trường hợp của tôi, tôi phải giả lập lớp thực và đặt các phương thức thành ảo, vì bạn không thể đưa tham số vào ctor của Giao diện. Đây có phải là cách tiếp cận đúng?
Houman

4
@Kave: Nếu bạn cần chèn một cái gì đó vào hàm tạo, bạn chắc chắn đang thử nghiệm sai thứ. Chế nhạo bất cứ thứ gì bạn cung cấp cho hàm tạo, thiết lập hành vi của nó và kiểm tra xem lớp này có hoạt động theo cách mà nó cần hay không. Nếu bạn cần, hãy viết một giao diện mới mà bạn thực hiện kiểu "được tiêm vào" để truy cập tất cả các chữ ký của phương thức.
Tomas Aschan
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.