views:

52

answers:

2

I have the following method:

User IDataContext.AuthenticateUser(string userName, string password)
{
   byte[] hash = PasswordHasher.HashPassword(userName, password);

   var query =
       from e in mContext.GetTable<User>()
       where e.Email == userName && e.Password == hash
       select e;

   return query.FirstOrDefault();
}

When mContext is a System.Data.Linq.DataContext everything works great. However, when mContext is an in-memory mock during my uniting testing, the comparison between e.Password and hash always returns false.

If I rewrite this comparison as e.Password.SequenceEqual(hash), then my unit tests will pass, but I get an exception when I'm talking to LinqToSql. (System.NotSupportedException: The query operator 'SequenceEqual' is not supported.)

Is there a way that I can write this query that will satisfy my unit tests with an in-memory mock, as well as the production component with LinqToSql?

+1  A: 

That's an interesting one. I can't think of a convenient way of intercepting the equals without breaking everything, but: are the user-names unique? You could just include the username condition in the LINQ, then check the hash in regular c#. In terms of data transferred there is little difference between passing it in and fetching it out, especially if we optimise for the success case (in which case this reduces the IO requirements).

Note: return the same result for "not found" and "not a match" if you do this.

Because the byte[] compare no longer depends on special treatment by LINQ-to-SQL, it should work fine in your mock now.

var user = (by name).SingleOrDefault();
if(user==null) #fail
bool hashMatch = /* compare array */
if (!hashMatch) #fail
return user;
Marc Gravell
A: 

This is not a good candidate for unit testing. What value is produced by testing SQL's equality by using .Net's equality?

In psuedocode, I see (in essence) three method calls:

HashPassword(); 
ConstructQuery();
FirstOrDefault();

Each of these three called methods may be unit tested. What's the point of unit testing the original method?

David B