Search code examples
c#unit-testingmockingxunit.netjustmock

Mocking and unit test passes even though assertion is not correct


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?


Solution

  • 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.)