Bharathi Mohan
Bharathi Mohan

Reputation: 56

Unit test using dependency injection and mock objects without hitting Database

I'm new to unit testing.Can anyone explain me about how to done unit testing without hitting Database.

And also i want to know that, Is dependency injection essential for unit testing? If yes, explain me with a sample code. It will be helpful for me.

I had already created unit testing for login, which hits Database. But i want to test the same case for the login, without hitting database. In this, i used Microsoft.VisualStudio.TestTools.UnitTesting.

Here is my code,

 [TestMethod]
    public void _01_LoginUser_01_Valid()
    {            
        BLUser.User.UserDTO user = new BLUser.User.UserDTO();
        user.UserName = "mohan";
        user.UserPassword = "abc";
        BLUser.Model.Fs_User result = BLUser.User.LoginUser(user);
        Assert.AreEqual("mohan", result.UserName);
    }

And my business logic is,

 public static Fs_User LoginUser(UserDTO userDTO)
    {                                   
        try
        {
            var context = new UserDBEntities();
            {                    
                var LoginUser = context.Fs_User.Where(u => u.UserName == userDTO.UserName && u.UserPassword == userDTO.UserPassword).SingleOrDefault();
                if (LoginUser == null)
                    ValidationError.LoginException((int)ExceptionCodes.InvalidPassword);
                return LoginUser;
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }                        
    }

Upvotes: 1

Views: 434

Answers (1)

David Osborne
David Osborne

Reputation: 6821

See my answer here: Solid Principle examples anywhere?

If you look at the idea of depending on an interface for your data access, you'll see how you could supply a 'fake' implementation of that interface for testing that would not depend on a database.

Based on your example, you need to make something like the following changes:

public class LoginThing
{
    private readonly IAmSomeContext context;

    public LoginThing(IAmSomeContext context)
    {
        this.context = context;
    }

    public Fs_User LoginUser(UserDTO userDTO)
    {                                   
        try
        {
            var LoginUser = 
                this.context.Fs_User
                    .SingleOrDefault(
                       u => 
                           u.UserName == userDTO.UserName 
                           && u.UserPassword == userDTO.UserPassword);

            if (LoginUser == null)
                ValidationError.LoginException((int)ExceptionCodes.InvalidPassword);

            return LoginUser;
        }
        catch (Exception ex)
        {
            throw ex;
        }                        
    }
}

And then your test can become something like:

[TestMethod]
public void _01_LoginUser_01_Valid()
{            
    BLUser.User.UserDTO user = new BLUser.User.UserDTO();
    user.UserName = "mohan";
    user.UserPassword = "abc";

    var fakeContext = CreateFakeContextWith(user);

    var thingUnderTest = new LoginThing(fakeContext);

    BLUser.Model.Fs_User result = thingUnderTest.LoginUser(user);

    Assert.AreEqual("mohan", result.UserName);
}

Creating the fake context would look something like this, if you used NSubstitute:

private IAmSomeContext CreateFakeContextWith(BLUser.User.UserDTO user)
{
    var fakeContext = Substitute.For<IFakeContext>();

    fakeContext.Fs_User.Returns(new List(new[] {user}));

    return fakeContext;
}

The syntax might not be exact, but you get the point...

Upvotes: 3

Related Questions