问题
I am using NHibernate and Rhinomocks and having trouble testing what I want. I would like to test the following repository method without hitting the database (where _session is injected into the repository as ISession):
public class Repository : IRepository
{
(... code snipped for brevity ...)
public T FindBy<T>(Expression<Func<T, bool>> where)
{
return _session.Linq<T>().Where(where).FirstOrDefault();
}
}
My initial approach is to mock ISession, and return an IQueryable stub (hand coded) when Linq is called. I have a IList of Customer objects I would like to query in memeory to test my Linq query code without hitting the db. And I'm not sure what this would look like. Do I write my own implementation of IQueryable? If so, has someone done this for this approach? Or do I need to look at other avenues?
Thanks!
回答1:
How I've done this test is to not pass the expression to the repository, instead expose IQueryable giving the repository an interface such as:
public interface IRepository<T>
{
IQueryable<T> All();
// whatever else you want
}
Easily implemented like so:
public IQueryable<T> All()
{
return session.Linq<T>();
}
This means that instead of calling your method on the repository like:
var result = repository.FindBy(x => x.Id == 1);
You can do:
var result = repository.All().Where(x => x.Id == 1);
Or the LINQ syntax:
var result = from instance in repository.All()
where instance.Id == 1
select instance;
This then means you can get the same test by mocking the repository out directly which should be easier. You just get the mock to return a list you have created and called AsQueryable() on.
As you have pointed out, the point of this is to let you test the logic of your queries without involving the database which would slow them down dramatically.
回答2:
From my point of view is this would be considered Integration Testing. NHibernate has it's own tests that it passes and it seems to me like you're trying duplicate some of those tests in your own test suite. I'd either add the NHibernate code and tests to your project and add this there along with their tests, thats if they don't have one very similiar, and use their methods of testing or move this to an Integration testing scenario and hit the database.
If it's just the fact you don't want to have to setup a database to test against you're in luck since you're using NHibernate. With some googling you can find quite a few examples of how to use SQLite to "kinda" do integration testing with the database but keep it in memory.
来源:https://stackoverflow.com/questions/448405/nhibernate-testing-mocking-isession