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десь? Ви знущаєтесь над класом чи інтерфейсом
Томаш Ашан

Так, я знущався над дафафактором та mockarticleDao у [Настройці] за допомогою інтерфейсу. DAO було зроблено за допомогою класу.
mrblah

@tomas Я оновив своє запитання кодом налаштування.
mrblah

2
Як ви бачите у моїй відповіді, вам потрібно або знущатися над інтерфейсом (саме це я рекомендую), або позначити GetByTitleметод virtual.
Томаш Ашан

Це також виглядає так, якби перший рядок у вашому тесті міг би бути переміщений у процедуру налаштування ...?
Томаш Ашан

Відповіді:


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
Якщо ви не можете знущатися над інтерфейсом, можливо, ви тестуєте неправильну річ ... але все-таки маркування методу віртуального вирішить проблему.
Томаш Ашан

+1 Томаш, мені потрібно ввести параметр в ctor, отже, в моєму випадку мені довелося знущатися над фактичним класом і встановлювати методи віртуальними, оскільки ти не можеш ввести параметри в ctor інтерфейсу. Це правильний підхід?
Хоуман

4
@Kave: Якщо вам потрібно щось ввести в конструктор, ви обов'язково перевіряєте неправильну річ. Знущайтеся над тим, що ви надаєте конструктору, налаштовуйте його на поведінку і перевіряйте, що цей клас поводиться так, як слід. Якщо вам потрібно, напишіть новий інтерфейс, який ви робите "введеним" реалізатором, щоб отримати доступ до всіх підписів методу.
Томаш Ашан
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.