patterncsharpMinor
Refactoring method to make it unit testing friendly
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
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 thSolution
Following on what Magnus said in comments can you not inject the necessary dependencies.
For example:
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.
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.