1

.net mvc 4 と流暢な nhibernate を使用してアプリケーションを作成しようとしています。

ProductsFacadeデータベースへのデータの取得と挿入を担当するものを作成しました。メソッドGetProductsByPageAndCategoryを使用して、データベースからレコードのページを取得します。ページネーションがうまく機能するかどうかをチェックする単体テストを書きたいです。

QueryOverページネーションは単一のクエリで行う必要があるため、これは困難です。データをフェッチするだけの別のメソッドを作成し、それをモックして、ページネーション用に別のメソッドを作成することはできません。したがって、データベースをモックする必要があります。モッキングには moq ツールを使用します。

多分誰かがそれを行う方法についていくつかのヒントを与えることができますか? または、私の問題を解決する他の方法はありますか?

public class ProductFacade {
    //...

    public virtual IList<Product> GetProductsByPageAndCategory(
        string category,
        int pageNumber,
        int pageSize)
    {
        //IList<Product> products = ;
        var productsQuery = _session.QueryOver<Product>();
        if (category != null)
        {
            productsQuery.Where(p => p.Category == category);
        }

        IList<Product> products = productsQuery
            .OrderBy(p => p.Id)
            .Desc
            .Skip((pageNumber - 1) * pageSize)
            .Take(pageSize)
            .List<Product>();

        return products;
    }

    //...
}
4

3 に答える 3

2

また、NHibernate セッションをモックするために moq を使用します。これは、NHibernateISessionとをモックする方法の非常に簡単な例ですISessionFactory

    var mockSession = new Mock<ISession>();
    mockSession.Setup(r => r.Get<ExampleEntity>(It.IsAny<int>()))
        .Returns(new ExampleEntity());

    var mockSessionFactory = new Mock<ISessionFactory>();
    mockSessionFactory.Setup(r => r.OpenSession())
        .Returns(mockSession.Object);

    var sessionFactory = mockSessionFactory.Object;
    // inject mockSessionFactory.Object to your business layer...

    // code where ever sessionFactory is used...
    // OpenSession now returns the mocked session
    using (var session = sessionFactory.OpenSession())
    {
        //Get of type ExampleEntity will always return whatever you define in your mock
        var rs = session.Get<ExampleEntity>(1);
    }

ビジネス オブジェクトにモッキングを使用するには、モックされたファクトリを使用するように手動で構築できるように設計する必要があります。

たとえば、Unity でインジェクションを使用する場合、通常、これは簡単です。ユニティを使用すると、ビジネスクラスのコンストラクターはセッションまたはファクトリなどを取得できます...この場合、ユニットテスト内でターゲットを手動で構築し、モックをそれに渡すことができます...

于 2013-09-29T14:16:12.000 に答える
2

これが私の代替手段です-データベースをモックしないでください。

私たちのテスト セットアップでは、すべての開発者のマシンに、指定された名前のデータベースが必要です (例: "CMS_AutoTests")。テストが実行されると、このデータベースと対話します。

TearDownテストの後に実行されるメソッドは、すべてのテーブルをクリアするストアド プロシージャを実行するため、各テストは空のデータベースから開始されます。

于 2013-09-29T20:59:17.320 に答える
2

インメモリデータベースは、モッキングよりもはるかにコードが少なく、理解しやすく、本物に近い. また、マッピングが正しいことを確認するため、追加の負荷保存テストは必要ありません。

//for all tests

static Configuration config;
static ISessionFactory testSessionFactory;

config = Fluently.Configure()
    .Database(SQLiteConfiguration.Standard.InMemory().ShowSql().FormatSql())
    .Mappings(m => m.AutoMappings.Add(AutoMap.AssemblyOf<Foo>())  // add your mappings here
    .BuildConfiguration();

testSessionFactory = config.BuildSessionFactory();

// in test
public ProductTests()
{
    session = sf.OpenSession();
    new SchemaExport(config).Execute(true, true, false, session.Connection, null);
}

private void InjectSampleData(params object[] objects)
{
    foreach (var obj in objects)
    {
        session.Save(obj);
    }
    session.Flush();
    session.Clear();
}

public void TestThis()
{
    InjectSampleData(
        new Product() { ... },
        new Product() { ... },
        new Product() { ... },
        new Product() { ... },
    );

    var products = new ProductFacade(session).GetProductsByPageAndCategory(...);

    // assert products match expected subcollection of Injected Data
}
于 2013-10-09T14:32:01.800 に答える