SubclassToTest is an AntiPattern: ---- '''AntiPattern Name''': ''SubclassToTest'' '''Type''': ''Design'' '''Problem''': Need to fake, mock or stub methods in a ClassUnderTest, and/or classes it uses. '''Context''': automated (xUnit) testing of one or more classes in a system '''Forces''': [forces] '''Supposed Solution''': * Subclass the ClassUnderTest. * Override method(s) that need to be faked/mocked/stubbed, for testing purposes. * Extract object creation methods for classes that this class creates that also need to be tested or mocked. ** Override these creation methods, creating fake/mock/stub subclasses, to override their methods. * Repeat for however many layers of classes needed. '''Resulting Context''': * No class used in the test is directly, fully, completely a ClassUnderTest. * It's difficult to succinctly describe or reason about the various methods being overridden, for each test. * It becomes more and more difficult to refactor production code, because any method not static, private or final, may have been overridden in one or more tests. * Seductive forces: why this is so popular: ** It's quick easy and simple. * Why, despite the seductiveness, this is actually a BadThing: ** Complexity grows rapidly and unpredictably. ** Reuse of test code is difficult. ** Refactoring of production code becomes more and more difficult. '''''Replacement positive patterns:''''' * DependencyInjection * ServiceLookup * AbstractFactoryPattern, with SingletonPattern, if needed. '''Design Rationale''': [rationale] '''Related AntiPattern''''''s''': '''Applicable Positive Patterns''': '''AntiPatternCategory''': DevelopmentAntiPattern / lack of ArchitectureAntiPattern '''Also Known As''': [other names] ---- '''Examples in the Literature''': ---- '''Examples in Practice''': ---- ---- '''''[Discussion]''''' ---- ''"Discussion"?? Here's a quarter, sonny. Go get yourself a language with DynamicTyping!'' Doesn't seem like DynamicTyping would avoid the problem; rather, it might make it worse, by making it more difficult to see the tests that are overriding ClassUnderTest methods. ---- In my opinion, SubclassToTest is a bad idea. First, I think having a UnitTest that needs to muck around in the implementation details of a class points to an encapsulation problem or maybe some problem with the abstraction. Second, SubclassToTest inhibits one's ability to refactor. However, if I restrict UnitTest''''''ing to public features, I am free to refactor the implementation and view the class from the ''using'' perspective. '''Therefore''', I always write UnitTest''''''s without violating the interface of the ClassUnderTest. After all, if you can't reach some behavior from the PublicInterface, why is it even in the class? '''As a result''' of doing this, I get to see my class from the perspective of class ''user'' rather than class ''provider''. If ''I'' end up feeling the desire to violate the abstraction, so will the ''real'' user. '''Therefore''', when you feel the desire to go beyond you public features, instead take the opportunity to revisit the design of your class interface. FWIW, I '''do''' have a parallel package hierarchy (as described above) so my tests can access package-data without having to be shipped with the production code. This way, you don't pollute the package namespace. I use JBuilder, so I just change my source path from "project\src" to "project\src;project\test". All my TestCase''''''s go into the "project\test" directory but look as if they are all one project to the IDE. However, I rarely, if ever have actually used this feature to access package visible attributes -- it's more just a convenient way to organize my test cases. { This is also the way Maven organizes the sources by default. } ''[Additional comment moved to AbstractTest.]'' -- RobertDiFalco ---- "The SubclassToTest AntiPattern should be banned." -- JeffGrigg ---- See also: SubclassToTestDiscussion ---- CategoryAntiPattern