
699
vary, however, in terms of how the logic is exposed. Regardless of how logic ex-
posure occurs, test-driven purists would prefer that tests verify that the Humble
Object is calling the extracted logic properly. This can be done by replacing the
real logic methods with some kind of Test Double (page 522) implementation.
Variation: Poor Man’s Humble Object
The simplest way to isolate and expose each piece of logic we want to verify is
to place it into a separate method. We can do so by using an Extract Method
refactoring on in-line logic and then making the resulting method visible from
the test. Of course, this method cannot require anything from the context. Ideally
everything the method needs to do its work will be passed in as arguments but this
information could also be placed in fi elds. Problems may arise if the testable com-
ponent needs to call methods to access information it needs and those methods
are dependent on the (nonexistent/faked) context, as this dependency makes
writing the tests more complex.
This approach, which constitutes the “poor man’s” Humble Object, works well
if no obstacles prevent the instantiation of the Humble Object (e.g., automatically
starting its thread, no public constructor, unsatisfi able dependencies). Use of a Test-
Specifi c Subclass can also help break these dependencies by providing a test-friendly
constructor and exposing private methods to the test.
When testing a Subclassed Humble Object or a Poor Man’s Humble Object,
we can build the Test Spy (page 538) as a Subclassed Test Double of the Humble
Object to record when the methods in question were called. We can then use
assertions within the Test Method (page 348) to verify that the values recorded
match the values expected.
Variation: True Humble Object
At the other extreme, we can put the logic we want to test into a separate class
and have the Humble Object delegate to an instance of it. This approach, which
was implied in the introduction to this pattern, will work in almost any circum-
stance where we have complete control over the code.
Sometimes the host framework requires that its objects hold certain responsi-
bilities that we cannot move elsewhere. For example, a GUI framework expects
its view objects to contain data for the controls of the GUI and the data that
those controls display on the screen. In these cases we must either give the test-
able object a reference to the Humble Object and have it manipulate the data for
that object or put some minimal update logic in the Humble Object and accept
that it won’t be covered by automated tests. The former approach is almost
always possible and is always preferable.
Humble Object
Humble
Object