4

ORMにNHibernate、単体テストにNUnit、DIにNinjectを使用してアプリケーションを開発しています。私は次のように ISession を嘲笑しています:

var session = new Mock<ISession>();

通常のモックされていないセッション オブジェクトを使用すると、次のような LINQ 拡張メソッドを使用してクエリを実行できます。

var result = Session.Query<MyEntity>();

しかし、次のコードでこれをモックしようとすると...

session.Setup(s => s.Query<MyEntity>());

...実行時に「サポートされていません」という例外が発生します。

Expression references a method that does not belong to the mocked object: s => s.Query<MyEntity>()

Moq/NHibernate でこのような基本的なクエリをモックするにはどうすればよいですか?

4

2 に答える 2

3

Query<T>()は拡張メソッドであるため、モックできません。@Rogerの回答が道ですが、特定のテストがあると便利な場合があります。NHibernate コードを読むか、独自のテストを使用して、メソッドが何をするかを調査しQuery<T>()、ISession に適切なメソッドを設定することができます。

警告:このようなセットアップを作成すると、テストが非常に壊れやすくなり、NHibernate の内部実装が変更されるとテストが壊れます。

とにかく、次の方法で調査を開始できます。

var mockSession = new Mock<ISession>(MockBehavior.Strict); //this will make the mock to throw on each invocation which is not setup
var entities = mockSession.Object.Query<MyEntity>();

上記の 2 行目は、例外をスローしISessionQuery<T>()拡張メソッドのどの実際のプロパティ/メソッドがアクセスしようとしているかを示すため、それに応じて設定できます。このまま進めていくと、最終的にセッションの適切なセットアップができ、テストで使用できるようになります。

注: 私は NHibernate に精通していませんが、他のライブラリの拡張メソッドを処理する必要があるときに上記のアプローチを使用しました。

于 2013-05-03T13:17:38.357 に答える
3

バージョン 5 の更新:

新しい NHibernate バージョンQuery<T>では、拡張関数ではなく ISession インターフェイスの一部であるため、簡単にモックできるはずです。

古い答え:

私はサニーの提案を試して、ここまで来ましたが、 が内部IQueryの にキャストされていて、NHibernate.Impl.ExpressionQueryImpl拡張できないと思うので行き詰まりました。これを投稿するだけで、他の失われた魂を数時間節約できます。

var sessionImplMock = new Mock<NHibernate.Engine.ISessionImplementor>(MockBehavior.Strict);
var factoryMock = new Mock<NHibernate.Engine.ISessionFactoryImplementor>(MockBehavior.Strict);
var queryMock = new Mock<IQuery>(MockBehavior.Strict);//ExpressionQueryImpl

sessionImplMock.Setup(x => x.Factory).Returns(factoryMock.Object);
sessionImplMock.Setup(x => x.CreateQuery(It.IsAny<IQueryExpression>())).Returns(queryMock.Object);
sessionMock.Setup(x => x.GetSessionImplementation()).Returns(sessionImplMock.Object);
于 2015-07-02T18:26:22.457 に答える