
601
Methods also help prevent Obscure Tests (page 186) by encapsulating
the mechanism of how the required objects are found and exactly which
objects to use, thereby enabling the reader to focus on understanding why
a particular object is being used and how it relates to the expected outcome
described in the assertions. This helps us move toward Tests as Documentation
(see page 23).
Although most Finder Methods return a single object reference, that object
may be the root of a tree of objects (e.g., an invoice might refer to the customer
and various addresses as well as containing a list of line items). In some circum-
stances, we may choose to defi ne a Finder Method that returns a collection (Array
or Hash) of objects, but the use of this type of Finder Method is less common.
Finder Methods may also update parameters to pass additional objects back to
the test that called them, although this approach is not as intent-revealing as use
of a function. I do not recommend initialization of instance variables as a way of
passing back objects because it is obscure and keeps us from moving the Finder
Method to a Test Helper (page 643) later.
The Finder Method can fi nd objects in the Shared Fixture in several ways:
by using direct references (instance variables or class variables initialized in the
fi xture setup logic), by looking the objects up using known keys, or by search-
ing for the objects using specifi c criteria. Using direct references or known keys
has the advantage of always returning exactly the same object each time the test
is run. The main drawback is that some other test may have modifi ed the object
such that it may no longer match the criteria implied by the Finder Method’s
name. Searching by criteria can avoid this problem, though the resulting tests
may take longer to run and might be less deterministic if they use different
objects each time they are run. Either way, we must modify the code in fewer
places whenever the Shared Fixture is modifi ed (compared to when the objects
are used directly within the Test Method).
Variation: SUT Encapsulation Method
Another reason for using a Test Utility Method is to encapsulate unnecessary knowl-
edge of the API of the SUT. What constitutes unnecessary? Any method we call on
the SUT that is not the method being tested creates additional coupling between
the test and the SUT. Creation Methods and Custom Assertions (page 474) are
common enough examples of SUT Encapsulation Methods to warrant their own
write-ups as separate patterns. This section focuses on the less common uses of
SUT Encapsulation Methods. For example, if the method that we are exercising
(or that we use for verifying the outcome) has a complicated signature, we
increase the amount of work involved to write and maintain the test code and may
Test Utility Method
Test Utility
Method
Also known as:
SUT API
Encapsulation