NHibernate试验、模拟试验

NHibernate试验、模拟试验,nhibernate,mocking,iqueryable,Nhibernate,Mocking,Iqueryable,我正在使用NHibernate和Rhinomock,在测试我想要的东西时遇到了困难。我想在不影响数据库的情况下测试以下存储库方法(其中_session作为ISession注入到存储库中): 公共类存储库:IRepository { (…为了简洁起见,代码被剪掉了…) 公共T FindBy(表达式,其中) { 返回_session.Linq().Where(Where).FirstOrDefault(); } } 我最初的方法是模拟ISession,并在调用Linq时返回一个IQueryab

我正在使用NHibernate和Rhinomock,在测试我想要的东西时遇到了困难。我想在不影响数据库的情况下测试以下存储库方法(其中_session作为ISession注入到存储库中):

公共类存储库:IRepository
{
(…为了简洁起见,代码被剪掉了…)
公共T FindBy(表达式,其中)
{  
返回_session.Linq().Where(Where).FirstOrDefault();
}
}
我最初的方法是模拟ISession,并在调用Linq时返回一个IQueryable存根(手工编码)。我有一个IList的客户对象,我想在memeory中查询,以测试我的Linq查询代码,而不影响数据库。我不确定这会是什么样子。我是否编写自己的IQueryable实现?如果是,是否有人为这种方法这样做?还是我需要寻找其他途径


谢谢

在我看来,这将被视为集成测试。NHibernate有它自己的测试,它通过了,在我看来,你似乎试图在你自己的测试套件中复制一些测试。我会将NHibernate代码和测试添加到您的项目中,并将其与他们的测试一起添加,如果他们没有一个非常相似的测试,则使用他们的测试方法,或者将其移动到集成测试场景中并点击数据库


如果只是因为您不想设置一个数据库来测试,那么您很幸运,因为您使用的是NHibernate。通过一些谷歌搜索,您可以找到许多示例,说明如何使用SQLite“有点”与数据库进行集成测试,但要将其保存在内存中。

我做此测试的方法是不将表达式传递到存储库,而是公开IQueryable,为存储库提供一个接口,例如:

public interface IRepository<T>
{
    IQueryable<T> All();
    // whatever else you want
}
你可以做:

var result = repository.All().Where(x => x.Id == 1);
或LINQ语法:

var result = from instance in repository.All()
             where instance.Id == 1
             select instance;
这意味着您可以通过直接模拟存储库来获得相同的测试,这应该更容易。您只需让mock返回您创建并调用AsQueryable()的列表


正如您所指出的,这样做的目的是让您能够在不涉及数据库的情况下测试查询的逻辑,而数据库会大大降低查询速度。

如果您的测试代码也调用result.FirstOrDefault();,您如何模拟代码?如果创建一个列表并对其调用AsQueryable(),那么.FirstOrDefault()将直接针对原始列表的内容工作。您不必模拟对queryable的任何调用,因为它是一个真实的、IQueryable对象。我们最终也使用了这种方法——它非常有效,尽管这意味着您的大多数存储库都有一个属性(在您的示例中为All(),在我们的示例中为queryable)
var result = repository.FindBy(x => x.Id == 1);
var result = repository.All().Where(x => x.Id == 1);
var result = from instance in repository.All()
             where instance.Id == 1
             select instance;