Many thanks to the Capital Area .NET UG for their hospitality last night. During my presentation on “TDD with ASP.NET” several interesting questions were raised and I have decided to repeat and answer them here (in no particular order):
- When should you use a mock object? What about mocking databases?
You should use a mock object in lots of different situations such as where the interaction is with an external system, or requires complex setup. It is also useful where you need to closely test the interactions between certain objects. In my work, I typically mock authentication systems (such as FormsAuthentication), messaging systems (SMTP) or other difficult to test systems.
However, I don't mock databases.
Many people in the community (and the published TDD books) talk about mocking out the database functionality. While this sounds great in principle, this doesn't seem to follow with the mainstream of *current* .NET development. Many .NET developers are still using DataReaders and DataSets and tying their data access directly to their business logic - or even worse ... directly to their UI. Then there is another generation (2nd?) which are using business objects to represent data and business logic - these objects manage their own persistence and several code generators exist (CodeSmith, etc) to generate such code. The next generation (3rd?) seems to be some sort of persistence manager (such as Java Data Objects in the Java world) which we should see in the next .NET release with ObjectSpaces.
Update (8/4/2004): I was just recently informed by Brian Noyes that ObjectSpaces is not expected to be in the 2.0 release but may be released shortly afterwards as an add-on.
So, where does all of this leave us with mocking databases? Being able to mock the database depends on pulling out the functionality for persistence and retrieval to one place (once and only once!) and then replacing that one place with a mock object - with current practices in .NET this is not easily done. Sure, you could roll your own persistence manager to just get and save objects but what about complex SQL queries and multiple joins or large complex searches? This is the realm of the typical corporate developer (we live and breathe databases/SQL) so a little mock object is just not going to cut it.
I use a unittest database with test data - it isn't always pretty (or fast) but it works.
- Why use “virtual” in the method signature when creating test cases?
Inheriting test cases for common functionality across different scenarios can be a very powerful way to test your application. Using virtual makes such inheritance and customizing within your TestFixtures much easier. I am also partial to virtual methods due to my Java background so I always use virtual methods as I hate the bugs that occur when methods are resolved by the type of the reference being used.
- What built-in support is there for asynchronous testing in NUnit?
There are no built-in abilities for doing such things and I can't think how it would be used if there were. However, tests are written in code (C# or whatever your .NET language of preference) and you can easily do anything that you need to do in certain situation such as launch new threads, etc.
(See this thread on the TDD Mailing List for more ideas on the topic of Asynchronous testing)
- How does TDD fit in with traditional unit testing in a strong QA environment?
In my experiences in traditional environments, unit testing is either not done or done after the fact (and often poorly) by the same developers who wrote the code. In this situation, TDD might replace such unit testing as it is being conducted by the same people and it is likely to be of higher quality if the TDD rules are being followed. If you have a separate QA team who would normally test the codebase using their own techniques and tools then let them keep doing what they are already doing. TDD is meant to provide the developer with a way to verify their code during development and provide a process for the design/development cycle - it is not meant to be a replacement for the QA process.
- What will change with the launch of Visual Studio.NET 2005 with respect to the .NET TDD tools available today?
VS.NET 2005 has a built in unit testing tool which is apparently very NUnit-like. There is also built-in coverage analysis which highlights the areas of code in red/green in the IDE showing the presence and absence of coverage. I believe that there may also be the ability to add “filters“ to the source control system in VS.NET Team System enforcing unit tests to pass for checkin, etc. There has also been some discussion on why the unit testing tools are only being included in the enterprise level tools. I hope to learn more about these features as I play with the beta release.
Over all, the session was successful but was very pressed for time. Scott Lock and Brian Noyes have asked me to return in a few months for Part 2 which will be delving further into the TDD coding sample, coverage analysis and so on!