TypeMock is wonderful
TypeMock is absolutely awesome. No, no, it is sexy. It is dead sexy. TypeMock has opened up a whole new world for me in unit tests. Scott Hanselman's podcast on mock objects came at the perfect time. It was literally that day, I was sitting there thinking "this is exactly what I need."
Previously, part of the trickery around unit testing was that it could be heavily dependent upon the data in the database or on outside systems. Want to have a test that makes a post to CS? Run it twice in a row and could run into an issue with the duplicate post checker. Want to test some Mail Gateway processing? It may need to connect to an IMAP/POP3 server to get some mail. There may not be any there.
There are a number of mock frameworks out there, and a number of great free ones. But one recurring thing I've seen is that they need the classes to be interfaces, so anything I want to override needs to be an interface, or they often can't access methods/properties that are static or something. Not with TypeMock.
I would definitely find needing to make everything an interface tedious. And on top of that, that wouldn't work for external libraries. Take the ASP.NET Profile class. It is not an interface, and I can't make it an interface. I could create our own Profile interface and change it all throughout CS, but is it worth it just for a unit test when there are easy alternatives? Perfect example of this was a unit test I wrote recently for testing processing of email templates. The template file it loads depends on the user's language setting. I can do a straight user.Profile.Language = "en-US", because the profile is read only be default, and there is a ton of work to make it writeable and everything. So, just mock it.
Mock profileMock = MockManager.MockAll(typeof (Profile)); profileMock.ExpectGetAlways("Language", "en-US");
Sweet. All done. Just create a mock and tell it to always return en-US for the Language.
In the same test, a part of the process is to queue the message, but that hits the DB and requires the DB connection all there. Don't want to both with that. DB is in separate tests, just want to test the actual processing of the email template. So mock the DB call so it doesn't actually go to it.
Mock queueMock = MockManager.MockAll(typeof (SqlEmailQueueProvider)); queueMock.ExpectCall("QueueEmail");
Writing a test on blogging by email and need to test it adding the post. But you don't want it to actually go to the DB, however, it needs to return a PostID after the post is created. No problem.
Mock weblogDPMock = MockManager.MockAll(typeof (WeblogSqlDataProvider)); weblogDPMock.AlwaysReturn("AddPost", BlogPostResults.Success).Args(Check.IsAny(), Check.IsAny(), new Assign(1));
Simply beautiful. I can sit there and test all day without worrying about having the proper set of sample data in the DB beforehand, getting duplicate post issues, or anything.