Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit Testing Authentication

Tags:

unit-testing

I am fairly new to unit testing. I am building an ASP.NET MVC3 application (although my question seems language agnostic) and am confused about a basic test.

I want to make a unit test that makes sure my "ValidatePassword" function works - It will take in a username and password, then hash the password and see if it matches the hash for a user in the database. If so, it returns true. The problem is that I am using a mock repository, so I will have to add the user to the db before running my test. I can't really create this user in my test setup because I don't know what the encrypted password will be until I actually run it through the function I am testing. Is the answer to run it through the Hash function once, write it down in my test, and then test with that?

Hope this is clear. Thanks!

like image 913
skaz Avatar asked Feb 25 '23 06:02

skaz


2 Answers

I prefer to set up my test data where possible through the public interface of my code, rather than giving the test code knowledge of how the code is implemented. So personally I would not use a hardcoded encrypted password in the test code. Let me explain...

Presumably, you have a method to add a new user, which internally will create an new entry in the database with a hashed password. Then the test would look something like this:

AddNewUser("username", "passsword");
bool isValid = ValidateUser("username", "password");
Assert.IsTrue(isValid);

This of course would have to be complimented with invalid user/password tests:

test: ValidUser_InvalidPassword:
    AddNewUser("username2", "pwd");
    bool isValid = ValidateUser("username2", "wrongPassword");
    Assert.IsFalse(isValid);


test: NonExistingUser:
    bool isValid = ValidateUser("non_existing_user", "anyPassword");
    Assert.IsFalse(isValid);

The argument against this would be that you are testing more than one unit in a single test. But personally I think this is better. Why?

Because the tests are not so brittle - i.e. if you make an internal change to the hashing algorithm the test is there to check that everything still works. You don't have to change the hard coded encrypted password in the test code.

That is one of the main benefits of unit tests: to check that we don't break anything when we refactor. So when we want to change the internal implementation for whatever reason (code cleanliness/performance or security improvements), the tests give us confidence that we have not broken the functionality.

An interesting article discussing the benefits of higher-level tests can be found in this Dr Dobbs article:

like image 141
GarethOwen Avatar answered Mar 13 '23 03:03

GarethOwen


Yes, you could have your setup function add the user with an hardcoded encrypted password to the mock repository. When unit-testing, you should use known values so that the behavior of the tested functions can be predicted.

like image 28
philant Avatar answered Mar 13 '23 01:03

philant