HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Refactoring method to make it unit testing friendly

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
refactoringmethodmakefriendlytestingunit

Problem

I have a completed application which I'm trying to write unit tests for (Yeah I know, talk about bad practices)

I have the following class here

public class UserManagementService : IUserManagementService
{    
    private static readonly IUserDao userDao = DataAccess.UserDao;
    private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

    public LoginResponse Login(LoginRequest request)
    {
        var response = new LoginResponse(request.RequestId);
        try
        {    
            var user = userDao.GetByUserId(request.UserId);
            if (user != null)
            {                   
                if (request.Password != "")
                {                        
                    if (Authenticate(user, request.Password))
                    {                          
                        return response;
                    }                        
                    response.ErrorCode = "IncorrectPassword";
                }
                else
                {                       
                    response.ErrorCode = "PasswordNotFound";
                }
            }
            else
            {
                response.ErrorCode = "UserNotFound";
            }
            response.Acknowledge = AcknowledgeType.Failure;
            return response;
        }
        catch (Exception ex)
        {
            Log.Error(ex);
            response.Acknowledge = AcknowledgeType.Failure;
            response.ErrorCode = "Exception";
            return response;
        }
    }

    public bool Authenticate(User user, string password)
    {           
        if (user == null) return false;

        using (var deriveBytes = new Rfc2898DeriveBytes(password, user.Salt))
        {
            var derivedPassword = deriveBytes.GetBytes(20);
            if (!derivedPassword.SequenceEqual(user.Password)) return false;
        }
        return true;
    }    
}


userDao follows th

Solution

Following on what Magnus said in comments can you not inject the necessary dependencies.

For example:

public class UserManagementService : IUserManagementService
{    
    private readonly IUserDao userDao ;
    private readonly ILog log;

    public UserManagementService(IUserDao userDao, ILog logger)
    {
       this.userDao = userDao;
       this.log = logger;
    }

    public LoginResponse Login(LoginRequest request)
    {
       // etc
    }  
}


Now the class has no dependencies on concrete implementations and you can mock the interfaces however you feel. For example, the ILog interface you might want to mock so it logs to the console only. The IUserDao interface might be mocked to a internal list implementation or you might use a mocking framework such as Moq.

Code Snippets

public class UserManagementService : IUserManagementService
{    
    private readonly IUserDao userDao ;
    private readonly ILog log;

    public UserManagementService(IUserDao userDao, ILog logger)
    {
       this.userDao = userDao;
       this.log = logger;
    }

    public LoginResponse Login(LoginRequest request)
    {
       // etc
    }  
}

Context

StackExchange Code Review Q#46172, answer score: 6

Revisions (0)

No revisions yet.