I have just started using Entity Framework(v4) and Linq.
I have a Entity data mod开发者_如何学Goel, which has been generated from a database. I have then implemented repository classes in order to implement the business logic for my entities and they contain my LINQ queries for interacting with the entities/database.
What is the easiest and simplest way to unit test the methods/functions in my repository classes without hitting the database?
You can run your tests against an inmemory database. Check this question
Find a framework that would allow you to create a mock-up repository. This will take time at the start, but will pay off in a long term run.
If you can pass in the IDbSet
into your repository that it is querying, you can easily write your own stub implementation of IDbSet
that reads from and writes to an in-memory collection mapped to an IQueryable
, or use a mocking framework to do it for you.
In your production code, you pass in the IDbSet
from the real DbContext
; in your test code, you pass in this stub.
If your repository under test references the DbContext
then you may want to refactor so that it only references an individual IDbSet
.
I assume that you just don't want to have to load/save any entities within your test (ie: test only your business logic, not the persistence layer). In that case you will need a way to easily generate (and re-use) test 'stubs'. Simplest way imo is to create some factories for your various entities that return some simple(but meaningful) entities.
For instance, if you were testing your User engine, you might want to have a testing factory that generates users of different types, maybe a User from Wisconsin, or a user with a VERY long last name, or a user with no friends, vs. a user with 100 friends, etc.
public static class UserStubFactory {
static User NewUserWithLongLastName(int letterCount) { //return user with long last name }
static User NewUserWithXFriends(int count) { //return user w/ X friends }
}
Then when you generate other test stub factories, you can start chaining them together. So maybe you'd want to test a User with a long last name, and then put them through some other actions within your system. Well now you already have the TestStub so you can simply call NewUserWithLongLastName() and pass him thru your engine.
If you're not of this method you can also just create them on the fly with the constructor syntax.
User newUser = new User() { LastName ="HOLYCOWTHISISAVERYYLONGLASTNAME"; }
but I prefer the factories for their re-usability factor.
精彩评论