Moq:在不可重写成员上的无效设置:x => x.GetByTitle(“ asdf”)


111

不确定如何解决此问题,尝试对方法“ 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);
}

单元测试:

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

运行测试给我错误:

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

更新资料

我的[Setup]样子是:

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

     _articleManager = new ArticleManager(_mockDaoFactory.Object);    
}

2
您实例化_mockDaoFactory并在_mockArticleDao某处吗?您是否在模拟类或接口
Tomas Aschan 09年

是的,我使用界面在[Setup]中嘲笑了daofactory和mockarticleDao。DAO是使用该类完成的。
mrblah

@tomas我用设置代码更新了我的问题。
mrblah

2
正如您在我的答案中看到的那样,您需要模拟接口(这是我推荐的接口)或标记GetByTitle方法virtual
Tomas Aschan,2009年

看起来好像测试中的第一行可以移到设置例程中...?
Tomas Aschan,2009年

Answers:


154

为了控制模拟对象的行为(至少在Moq中如此),您需要模拟一个接口,或者确保您尝试控制的行为被标记为虚拟。在您的评论中,我理解了这一点,因此实例化_mockArticleDao如下所示:

_mockArticleDao = new Mock<ArticleDAO>();

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

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

否则(这是我的建议),而是模拟接口。

_mockArticleDao = new Mock<IArticleDAO>();

但是由于ArticleDAO继承自Generic ....,因此,如果我模拟接口,则GenericNhibern中的方法。不会提供?
mrblah

因为工厂发出的对GetArticleDAO的调用返回的是ArticleDAO而不是IArticleDAO,所以b / c articleDAO还会绑定到其中包含休眠内容的抽象类。
mrblah

2
如果您无法模拟该接口,那么您可能正在测试错误的东西……但是,仍然可以将方法标记为虚拟将解决问题。
Tomas Aschan 09年

+1 Tomas,我需要向ctor中注入一个参数,因此,在我的情况下,我不得不模拟实际的类并将方法设置为virtual,因为您无法将参数注入到Interface的ctor中。这是正确的方法吗?
Houman

4
@Kave:如果需要在构造函数中注入某些东西,则肯定是在测试错误的东西。模拟您提供给构造函数的一切,设置其行为并测试此类的行为。如果需要,编写一个新接口,使“注入”类型实现,以访问所有方法签名。
Tomas Aschan
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.