I recently attended a presentation on generics by Jean Paul Boodhoo for the Austin .Net User Group. The presentation was nothing short of amazing for many reasons, but I will save the details of that for another time. For now, I want to focus on a seemingly insignificant practice that I picked up from him there. Within his unit tests, he uses a method called CreateSUT() to instatiate the class under test. (SUT stands for System Under Test.)
[Test] public void Should_do_something() { VideoGameLibrary library = CreateSUT(); library.doSomething(); Assert.IsTrue( library.hasDoneSomething ); } private VideoGameLibrary CreateSUT() { // Setup dependencies...then instantiate the class to test. return new VideoGameLibrary(dependency1, dependency2, etc..); }
My first reaction to this practice was to think that it was quite useless. I thought to myself “Why not just put it in the TestSetup?” I answered that question on my own today as I began to write some tests for a class that had a lot of constructor-injected dependencies. It took several lines of code to create the dependencies for this class, and then one long line of code to call its constructor and inject those dependencies. The code was ugly, and repeated in every test…can you say code smell? It obviously needed refactoring.
I refactored the tests to remove the duplicated code that created all the dependencies and placed them within the TestSetup(). However, I found my self hesitating to to move the creation of the primary object I was testing. Moving it to the TestSetup() would make the test a bit less clear. I prefer to have as much of a test’s details and dependencies as possible to be declared within the test itself. That way I don’t have to look far to see what I am testing. However, moving this to the TestSetup would result in using class-variables to store the object under test. From the TestMethod’s standpoint, I would just be using a class-variable that had been instantiated somewhere. There would be no apparent details of the creation of the object within the test, so the user would have to look at the TestSetup.
Using CreateSUT() alleviates both the duplicate code and readability issues. You get the best of both worlds. You get to consolidate the setup code into one place, and you get readability by instantiating the system under test right within your test method. This makes it clear which class you are testing, its type, and where to find the code that constructs it.
Because I value clarity so highly, I will definitely be using this pattern in my testing. While on the surface it seems to be next to useless, it does have value.
-=CE=-