Testing Around ASP.NET Cache Features
It's still quite painful to try and test code that relies on ASP.NET Caching. Now, I love caching. Ask anybody. But testing around it can pretty much suck. The biggest source of pain for me at the moment is the SqlCacheDependency, which is freaking awesome in terms of functionality but freaking annoying in terms of testing around it. I have integration tests that, for some reason, occasionally fail claiming that "table X is not configured for SQL Cache dependency." This, despite a SQL script that runs before every test and ensures that yes, in fact, those tables are configured. But even leaving integration tests out of the picture, unit testing classes that rely on logic that might touch a SqlCacheDependency is extremely difficult, because you cannot easily use Dependency Injection to mock away the dependency. And hardcoded into the SqlCacheDependency is logic that tries to talk to a real database instance (to do the aforementioned check whether the table in question is configured for the cache dependencies).
Speaking with Roy Osherove about this issue, he assured me that TypeMock handles this easily, and also pointed me toward Ivonna, which is an in-memory ASP.NET testing tool that sounds somewhat similar to the Plasma project I worked on a long while ago (except that it sounds like this one might actually go somewhere). Thus far I've only used Rhino Mocks for my mocking needs, but I think I'm going to have to give TypeMock a try in the near future to see how well it handles some of these issues (and if Rhino Mocks can mock SqlCacheDependency, please let me know how).
The way I handle this now is like this:
public SqlCacheDependency GetSqlCacheDependency(){ try {System.Web.Caching.SqlCacheDependency sqlDependency =
new SqlCacheDependency(LQSiteConfig.Settings.SqlCacheDatabaseName, tableDependency); return sqlDependency;}
catch (Exception ex) {if (PersistenceLayer is SqlPersistenceLayer)
{ // log it; otherwise ignore it}
}
return null;
}
Essentially this will ignore any exceptions generated by the SqlCacheDependency when I'm in a unit test, as the PersistenceLayer in that case will be mocked.




Comments
ftorres said on 09 Jul 2008 at 11:48 PM
For a more traditional way to test web form
in C# or VB.NET integrated with Visual Studio, check out www.InCisif.net.
ulu said on 11 Jul 2008 at 7:11 AM
Actually, it was Plasma that inspired me to make Ivonna!
Assuming that we forget about the testability issues here, it would be logical to put the code that references System.Web in the UI layer. When the next logical step is to test it with Ivonna. Now, the current edition is more suitable to test pages, but there's a possibility to attach a handler to, say, the Page.Init event. The handler would execute the test code in the Asp.Net context (if you need that). Alternatively, you can precompile your app (or use a Web Application project) and test your class directly. Both ways, you can mock the SqlCacheDependency constructor with TypeMock easily.
One of the examples where TypeMock improves both testability and quality of your code.
Paul Jones said on 23 Oct 2008 at 1:08 PM
Hey Steve! Nice post.
SQLCacheDependency is a cool feature but its problems go beyond testing. It is not scalable and causes lots of other problems for developers. For a detailed look please visit my blog.
Cheers!
ssmith said on 23 Oct 2008 at 2:54 PM
@Paul Jones,
It's not fair to say it isn't scalable - it does just fine in single server environments and even scales well for multiple server farms (for instance, my 3-node farm uses it quite effectively to serve over 150 million requests per month). There are alternatives like ScaleOut StateServer and eventually Microsoft Velocity (and yes, Alachisoft NCache as well) for the larger web farm scenarios, though.
Paul Jones said on 23 Oct 2008 at 4:30 PM
Steve,
ASP.NET Cache being stand-alone & InProc is the real problem. Trying to "simulate" distribution through SqlCacheDependency is really a "hack" in my opinion. The right way to solve this scalability problem is through an in-memory distributed cache.
And, Microsoft is finally realizing it as well. They're working on Velocity but that is still in its infancy and will take some time to stabalize and mature.
I personally like NCache which is really impressive because of its rich set of caching topologies (Mirrored, Replicated, Partitioned, Partition-Replica, and Client Cache). The cool thing is that it also has NCache Express which is free for 2-server environments.
Check it out at: www.alachisoft.com/.../rp.php
ssmith said on 23 Oct 2008 at 4:44 PM
I know you like NCache - it's mentioned (exclusively) in every one of your blog posts - that's why I thought it would be worthwhile to mention some others as well to give readers a somewhat less biased take on things.
And yes, I agree, an in-memory distributed cache is certainly the right way to solve the multi-server cache problem. I'm happy to see one is coming out-of-the-box, and of course there are several third party offerings that are quite mature and work well. Including NCache.