Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Comparing byte[] in LINQ-to-SQL and in a unit test that uses mocking

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?

like image 342
Kyle Chafin Avatar asked Sep 19 '10 00:09

Kyle Chafin


People also ask

What mocking frameworks have you used for unit testing?

Many mocking frameworks for Java code work in combination with JUnit and other popular unit testing frameworks, and are great depending on your specific needs. Two of the most widely used are Mockito and PowerMock. Mockito is useful for all but the most complicated cases, for which you can use PowerMock instead.


1 Answers

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;
like image 75
Marc Gravell Avatar answered Nov 09 '22 12:11

Marc Gravell