0

I am working with TDD and all is going well. When I get to my actual Repository though I don't know how to test this.

Consider the code below - this is what I know I want to write but how do I tackle this in a test first way without doing integration testing.

public class UserDb : IUserDb
{
    public void Add(User user)
    {
        using (var context = new EfContext())
        {
            context.Users.Add(user);

            context.SaveChanges();
        }
    }
}

The link below by forsvarir is what I want to put as an answer. How I can do that?

http://romiller.com/2012/02/14/testing-with-a-fake-dbcontext/

8
  • Hi Dave, I'm wondering if it is necessary to get this code under test... You would rather test EntityFramework functions than your business logic... Commented May 22, 2015 at 12:16
  • @sebastian87 I think you meant the other way around. You would rather test your business logic than EF functions. Commented May 22, 2015 at 12:28
  • Me no english, me name potato. But you are right, that's the way I meant it. Commented May 22, 2015 at 12:31
  • I am testing my business logic of course. I am trying to do 100% TDD. So I am writing a test for UserDb.Add first and then need to write the code to make the test pass. That will be something like the code I posted but this makes actual DB calls. Commented May 22, 2015 at 15:51
  • 1
    Depending on your EF version, you might want to have a look at EF6 msdn.microsoft.com/en-gb/data/dn314429.aspx earlier versions romiller.com/2012/02/14/testing-with-a-fake-dbcontext Commented May 23, 2015 at 19:55

2 Answers 2

1

The usual answer to these kinds of questions is:

  • Isolate the hard to test dependencies (the EF context)
  • Provide a fake implementation in your tests to verify the correct behaviour of the SUT

This all makes sense when you have interesting logic to test in your system under test. For your specific case, the repository looks like a very thin abstraction between your clean domain and EF-aware logic. Good, keep 'em that way. This also means that it's not really doing much work. I suggest that you don't bother writing isolated unit tests (wrapping EF DbContext seems like extra work that might not pull its weight).

Note that I'm not saying you shouldn't test this code: I often tend to test these thin repositories using a real database, i.e. through integrated tests. For all the code that uses these repositories however, I'd stick to isolated unit testing by providing fake repositories to the system under test. That way I have coverage on my repository code and test that EF is actually talking to my database in the correct way and all other tests that indirectly use these repositories are nice, isolated and lightning-fast.

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

Comments

1

What are you hoping to achieve by testing the 3rd party tool? You could mock out the context var fakeContext = A.Fake<IDbContext>(); and then assert that an attempt was made to write to the database. A.CallTo(() => fakeContext.SaveChanges()).MustHaveHappened();

The above example uses FakeItEasy mocking library.

3 Comments

I don't want to test the third party tool - just my Add method. What you are suggesting sounds along the right lines. I am using RhinoMocks though. IDbContext doesn't exist though so I not sure how to create such an interface for an Entity Framework context.
In general it's not necessary to "test a 3rd party tool", but I have found that EF often acts unexpectedly or just plain crashes at runtime (e.g. a LINQ query that cannot be translated to SQL). Call me paranoid -or even not experienced enough with EF- but when I'm TDD'ing data-access code I like to know whether the code will actually run against a real SQL database.
@prgmtc I absolutely agree with you about the paranoia. I tend to write a number of integration tests against EF. Having come to EF from nHibernate I tend to put all my EF bits inside transactions, and I simply have not found an effective way to mock them. That said, my first pass of tests is always decoupled unit tests, this way I can be sure that the logic has been pushed out of the data access to the business layer (I'm well behaved that way at least).

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.