Moq:非可覆盖成员的设置无效:x => x.GetByTitle("asdf")

mrb*_*lah 108 c# nhibernate resharper nunit moq

不知道如何解决这个问题,尝试对方法"GetByTitle"进行单元测试

以下是我的定义:

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);
}
Run Code Online (Sandbox Code Playgroud)

单元测试:

[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);
}
Run Code Online (Sandbox Code Playgroud)

运行测试给出了错误:

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

更新

[Setup]看起来像:

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

     _articleManager = new ArticleManager(_mockDaoFactory.Object);    
}
Run Code Online (Sandbox Code Playgroud)

Tom*_*han 150

为了控制模拟对象的行为(至少在Moq中),您需要模拟一个接口,或者确保您尝试控制的行为标记为虚拟.在你的评论中,我理解它,以便实例化_mockArticleDao是这样的:

_mockArticleDao = new Mock<ArticleDAO>();
Run Code Online (Sandbox Code Playgroud)

如果要保持原样,则需要标记GetArticle方法virtual:

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

否则(这是我推荐的),改为模拟界面.

_mockArticleDao = new Mock<IArticleDAO>();
Run Code Online (Sandbox Code Playgroud)

  • @Kave:如果你需要在构造函数中注入一些东西,你肯定是在测试错误的东西.嘲笑你给构造函数的任何东西,设置它的行为并测试*this*类的行为方式.如果需要,编写一个新的接口,您可以使用"注入"类型的工具来访问所有方法签名. (4认同)
  • 如果你不能模拟界面,那么你可能正在测试错误的东西......但是,将虚拟方法标记为可以解决问题. (2认同)