Class MyBusinessService
new MyBusinessService(data).doBusinessOperationXyz()
. No need to make
such classes stateless, or worse, singletons; instead, it's designed as a proper object.
One of those "untestable" idioms is the use of a static persistence facade (the
Database class) for high-level database operations in the context of a
thread-bound work unit. Since all interaction with the facade is through static
methods, client classes
cannot be unit tested with a tool which only supports mock objects. With JMockit, though, writing such a
test is just as easy as any other (even easier, in fact, given that static
methods don't require an
instance of the mocked class at all).
Another idiom which runs against limitations of other mocking tools is the direct instantiation and use of external
dependencies, such as the Apache Commons Email API, used here to send
notification e-mails. As demonstrated here, sending an e-mail is simply a matter of instantiating the appropriate
Email
subclass, setting the necessary properties, and calling the send()
method. It is
certainly not a good use case for Dependency Injection (DI).
Finally, consider that application-specific classes like this one are inherently non-reusable in different
contexts/applications; as such, they can and should be made final
to reflect the fact that they are not
supposed to be extended through inheritance. In the case of reusable base classes, which are specifically
designed to be extended through inheritance, the judicious use of final
for public
and
protected
methods is important. (The description of the Template Method pattern in the "GoF"
book explains why a properly designed template method should be non-overridable.) Unfortunately, the practice of
designing for extension conflicts with the particular implementation approach employed by other mocking
tools, which dynamically generate a subclass overriding all non-final
methods in the mocked class in
order to provide mocked behavior. For JMockit, on the other hand, whether a method or class to be mocked is
final
or not is irrelevant, as a radically different mocking approach is employed: class
redefinition as provided by
Instrumentation.redefineClasses(java.lang.instrument.ClassDefinition...)
.
-
Constructor Summary
Constructors -
Method Summary
-
Constructor Details
-
MyBusinessService
-
-
Method Details
-
doBusinessOperationXyz
public void doBusinessOperationXyz() throws org.apache.commons.mail.EmailException- Throws:
org.apache.commons.mail.EmailException
-