1

I have the following method:

Void UpdateUser(User user){}

I need to check this method whether will work properly.

I've used a separate db to check this in unit testing. But many experienced people said if I use this method that won't be unit testing; that's integration testing.

But I don't know how to mock for unit testing.

The code written in the UpdateUser method, will try to update data using Entity framework.

If I mock (Actually I don't how to do this either), how this will work with entity framework?

Mansfield
  • 14,445
  • 18
  • 76
  • 112
Jeeva J
  • 3,173
  • 10
  • 38
  • 85
  • 1
    There are hundreds of blogs and thousands of questions on mocking databases using Entity Framework. What did you try, what did you find, what didn't work on that? – CodeCaster Oct 23 '13 at 12:23
  • 1
    The underlying issue you're trying to get at is how to implement Dependency Injection. I suggest starting your research there. [Why does one use dependency injection?](http://stackoverflow.com/q/14301389/580951) – Dustin Kingen Oct 23 '13 at 12:25
  • Please post your custom Data Context class - the one containing the `DbSet` properties so that I can post an answer that matches your setup. – Keith Payne Oct 23 '13 at 12:46

6 Answers6

4

Mocking means that you develop your software components (classes) in a way that any class with behaviour is used/consumed/called-upon as an interface (or abstract class). You program to an abstraction. Run-time you use something (service locator, DI container, factory, ...) to retrieve/create those instances.

The most common way is to use construction injection. Here is an excellent explanation of why one would use DI, and examples of how to do it.

In your case, your component that uses the Entity Framework (your repository for instance) must implement a repository-interface, and any class that uses your repository should use it as an interface.

This way, you can mock the repository in your unittests. Which means that you create a unit-test-repository class (which has nothing to do with any database or EF), and use that when you create the instance of the class that you want to unit-test.

Hopefully this helps. There are many source to be found. Personally I just read this book and I found it to be very good. This is the authors blog.

Community
  • 1
  • 1
Maarten
  • 22,527
  • 3
  • 47
  • 68
0

You can use transaction and rollback or create a test user try its update. Assert and then in the finally block delete the test user.

You can use mocking framework like moq, rhino etc. moq is quite easy and you can find many example that demonstrate moq with DI like unity framework.

Girish Sakhare
  • 743
  • 7
  • 14
  • 3
    -1 Rolling back the database is testing, but it is not *unit testing*. – Keith Payne Oct 23 '13 at 12:26
  • @KeithPayne, Please post your answer regarding what I asked. I've to do unit testing, not integration testing. Please post your valuable answer – Jeeva J Oct 23 '13 at 12:27
  • @DavidArno Because you cannot lock up the database within the context of the unit test to prevent another process from modifying the underlying data, it cannot be deterministic. It will fail if other similar database-dependent tests are run simultaneously and all of these tests are not coded with the knowledge of all other possible tests to guard against unexpected data. – Keith Payne Oct 24 '13 at 14:32
0

If your class is like this

public class UserRepository()
{
    Sqlcontext _context;
    void UpdateUser(User user)
    {
       _context.Users.Add(user);
    }
}

then this is not unit testable.

Although this is not a unit test, if you insist on connecting on database and testing it, you could change your function to

User UpdateUser(User user)
{
    _context.Users.Add(user);
    return user;
}

and test if

user.Id > 0  

Here, you are basically just testing entity framework.

sunil
  • 5,078
  • 6
  • 28
  • 33
0

"I've used a separate db to check this in unit testing. But many experienced people said if I use this method that won't be unit testing; that's integration testing."

Those people are mistaken, despite their supposed experience. For some reason, the incorrect notion that unit tests are all about testing parts of your code in isolation has grown in popularity in recent years. In reality, unit testing is all about writing tests that act as a unit, in other words they exist in isolation and the result of one unit test cannot influence another test.

If your UpdateUser method directly accesses EF, then as long as you ensure the database is guaranteed to be rolled back to its starting state at the end of each test, then you have unit tests. However, setting the database up for each test and ensuring it can be reliably rolled back can be a lot of work. That is why mocks are often used. Other answers have covered mcoking EF, so I won't go over that.

To greatly simplify your tests, you could have an extrapolation layer between UpdateUser and EF. In other words, the UpdateUser class is supplied with an instance of an interface, which is its gateway into EF. It doesn't talk to EF directly. To then mock EF, you simply supply a mocked implementation of the interface. This then pushes the need to test against EF down into a more basic layer, with more basic CRUD-like behaviours.

David Arno
  • 42,717
  • 16
  • 86
  • 131
  • With more respect than you've shown others of supposed experience, the problem is not isolation but the nature of databases. If the OP was using a separate database instance on every thread, then testing all the way through the database can be a unit test. Even tests that bounce off of a separate component can be unit tests, as long as the test is fast, automated, isolated, and deterministic. Deterministic is the killer when testing to a database. There just isn't any way to remove the potential for unexpected data from other processes/threads. – Keith Payne Oct 24 '13 at 14:36
  • @KeithPayne, damn, I find myself having to agree with you. :) When one takes into account running tests in parallel, DB tests indeed cannot be unit tests. And true unit tests have to support being run in parallel. – David Arno Oct 24 '13 at 15:20
0

A non official trick, not-best-practice can be to use an in-memory database (context) for the time of testing.

Estevez
  • 1,014
  • 8
  • 13
-1

Use transaction and rollback your transaction at the end of test

Troopers
  • 5,127
  • 1
  • 37
  • 64
  • Yes, That's what I'm doing ? But anyway, people said to mock. I too feel that's the good way of programming – Jeeva J Oct 23 '13 at 12:22