I'm very new to unit testing and TDD on a whole.
I have the following Login method in my Service layer (WCF) which is hosted as a windows service. My service layer follows the facade pattern, and all calls to the service layer are made with requests objects and returns the corresponding response object.
public LoginResponse Login(LoginRequest request)
{
var response = new LoginResponse(request.RequestId);
try
{
if (!ValidRequest(request, response, Validate.ClientTag))
return response;
var user = userDao.GetByUserId(request.UserId);
if (user != null)
{
if (request.Password != "")
{
var authenticationService = new AuthenticationService();
if (authenticationService.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;
}
}
Both lines here:
userDao.GetByUserId(request.UserId);
and
authenticationService.Authenticate(user, request.Password);
are making calls to the DB.
Here's the test I've written with xUnit and JustMock:
[Theory]
[InlineData("manager", "manager")]
public void LoginTest(string userId, string password)
{
//Arrange
var userServiceMock = Mock.Create<IUserManagementService>();
var request = new LoginRequest().Prepare();
request.UserId = userId;
request.Password = password;
var response = new LoginResponse(request.RequestId);
Mock.Arrange(() => userServiceMock.Login(request)).Returns(response).OccursOnce();
//Act
userServiceMock.Login(request);
//Assert
Mock.Assert(userServiceMock);
}
The problem I'm having is even after I've changed my service method to
public LoginResponse Login(LoginRequest request)
{
return null;
}
My test still passes. What am I doing wrong?
You are not testing anything. You are mocking your system under test which is not correct.
See this answer for a brief explanation of what a mock is.
If you are testing UserManagementService.Login()
you'd want:
[Theory]
[InlineData("manager", "manager")]
public void LoginTest(string userId, string password)
{
// Arrange
// System under test
IUserManagementService userService = new UserManagementService();
var request = new LoginRequest().Prepare();
request.UserId = userId;
request.Password = password;
var expectedResponse = new LoginResponse(request.RequestId);
//Act
var actualResponse = userService.Login(request);
//Assert
Assert.AreEqual(actualResponse.Something, expectedResponse.Something);
}
No need to mock anything. (You may need to mock any dependencies that Login()
has such as AuthenticationService
, userDao
and even Log
if you don't want your unit test to write to the log.)