4

I have just started using Entity Framework(v4) and Linq.

I have a Entity data model, 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?

3
  • 1
    you have to use mocking framework,my suggestion is to go for Rhino-Mocks Commented Jun 10, 2011 at 13:55
  • See this article: bit.ly/bF7jL3. Commented Jun 10, 2011 at 14:36
  • Don't use a mocking framework. In the long term they only make your unit tests hard to read, thus hard to maintain. Commented Jun 10, 2011 at 14:37

4 Answers 4

3

You can run your tests against an inmemory database. Check this question

Sign up to request clarification or add additional context in comments.

3 Comments

I agree with Jason. The option given by Ladislav Mrnka in the referenced question doe mean you still need to clean up the database after each test or run everything inside of a database transaction. In other word, you are still doing integration testing rather than unit testing in that case.
I agree with both @Jason and @Steven. These will definitely be integration tests.They will be run in memory for speed with a controlled input data. After each test the data needs to be cleaned up and repopulated to make sure tests don't affect each other.
@jfar. I'm not talking about testing a Linq to objects provider but actually testing the real data access layer. Instead of using the original database I suggest a lightweight or in-memory database should be used.
1

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.

Comments

1

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.

Comments

1

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.

1 Comment

NO NO - Do not write integration tests with a linq provider. Linq to objects will work 100% of the time. A sql based linq provider will work "some" of the time because certain expression trees can't be converted to sql. Your tests may pass but code will fail in runtime.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.