JUnit provides a number of other variants on these features, including @BeforeClass to execute one-
time setup for all the test methods in a given test class, @Ignore to indicate test methods and classes to
skip, and @RunWith to indicate a class to run your test case other than the default used by JUnit. However,
those are outside of the scope of this topic. The goal of this section is to give you the tools required to be
able to test your batch processes. Using just the @Before , @Test , and @After annotations along with the
assert methods available on JUnit's Assert class, you can test the vast majority of scenarios required.
But there is a small catch. The earlier unit-test definition said that unit testing is the testing of
components in isolation. How can you test a data access object (DAO) using JUnit when it depends on
JDBC and a database? How about testing an ItemStream, which requires you to use Spring Batch
components as some of its parameters? Mock objects fill this void, and you look at those next.
It would be very easy to write software like the String object tested earlier, which has no dependencies.
However, most systems are complex. Batch jobs can require dozens or more classes and depend on
external systems including application servers, JMS middleware, and databases, just to name a few. All
these moving parts can be difficult to manage and provide interactions that are outside the scope of a
unit test. For example, when you want to test the business logic for one of your ItemProcessors, do you
really need to test that Spring Batch is saving the context correctly to your database? That is outside the
scope of a unit test. Don't get this wrong—that does need to be tested, and you look at it later in this
chapter. However, to test your business logic, you don't need to exercise the various dependencies that
your production system interacts with. You use mock objects to replace these dependencies in your
testing environment and exercise your business logic without being effected by outside dependencies.
Note Stubs are not mock objects. Stubs are hard coded implementations that are used in testing where mock
objects are reusable constructs that allow the definition of the required behavior at run time.
Let's take a minute to call out that mock objects aren't stubs. Stubs are implementations that you
write to replace various pieces of an application. Stubs contain hard-coded logic intended to mimic a
particular behavior during execution. They aren't mock objects (no matter what they're named in your
How do mock objects work? There are essentially two different approaches most mock object
frameworks take: proxy based and class remapping. Because proxy-based mock objects are not only the
most popular but the easiest to use, let's look at them first.
A proxy object is an object that is used to take the place of a real object. In the case of mock objects, a
proxy object is used to imitate the real object your code is dependent on. You create a proxy object with
the mocking framework and then set it on the object using either a setter or constructor. This points out
an inherent issue with mocking using proxy objects: you have to be able to set up the dependency
through an external means. In other words, you can't create the dependency by calling new MyObject()
in your method, because there is no way to mock the object created by calling new MyObject() . 3 This is
3 This isn't 100% true. PowerMock lets you mock the new operator. You can find more information on
PowerMock at http://code.google.com/p/powermock/.