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

はい、インターフェイスを使用して[設定]でdaofactoryとmockarticleDaoをモックしました。DAOはクラスを使用して行われました。
mrblah 2009

@tomas質問をセットアップコードで更新しました。
mrblah 2009

2
私の答えでわかるように、インターフェイスをモックする(推奨)か、GetByTitleメソッドにマークを付ける必要がありますvirtual
Tomas Aschan 2009

また、テストの最初の行をセットアップルーチンに移動できるようにも見えます...?
Tomas Aschan 2009

回答:


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 2009

ファクトリからGetArticleDAOを呼び出すと、IArticleDAOではなくArticleDAOが返されるため、b / c articleDAOは、nhibernateのものを含む抽象クラスにもバインドします。
mrblah 2009

2
インターフェースをモックできない場合は、間違ったものをテストしている可能性があります...しかし、メソッドをvirtualとマークすると問題が解決します。
Tomas Aschan 2009

+1トーマス、パラメーターをctorに注入する必要があるため、パラメーターをインターフェースのctorに注入できないため、私の場合は実際のクラスをモックしてメソッドをvirtualに設定する必要がありました。これは正しいアプローチですか?
ホウマン、2011

4
@ケイブ:コンストラクタに何かを注入する必要がある場合、間違いなく間違ったものをテストしています。コンストラクターに与えたものをすべてモックし、その動作を設定し、このクラスが適切に動作することをテストします。必要に応じて、すべてのメソッドシグネチャにアクセスするために、「注入された」型を実装させる新しいインターフェイスを記述します。
Tomas Aschan
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.