Writing JUnit using the Spring context

In the previous sections, we looked at how to launch a Spring context from the main method. Now, let's shift our attention to launching a Spring context from a unit test. We will use the JUnit framework as our unit testing framework.

When we write a unit test with the Spring Framework, we need to launch an application context. The application context initializes all of the beans and dependencies. We can get the beans from the application context and check whether they return expected values.

To launch an application context in a unit test, we can use SpringJUnit4ClassRunner.class as a runner:

    @RunWith(SpringJUnit4ClassRunner.class)

Let's launch the application context with XML configuration. Here's how you can declare this:

    @ContextConfiguration(
locations = { "/BusinessApplicationContext.xml" }
)

Once the application context is launched, we want to get the beans from the application context and use them in the unit test. The Spring test framework provides simple annotations to use beans from the application context in the test. All that you would need to do is to define a member variable in the test with the @Autowired annotation. The following snippet shows how we can get an implementation of BusinessService autowired into the unit test:

    @Autowired 
private BusinessService service;

Earlier in this chapter, we created a dummy implementation of DataServiceImpl. The retrieveData method returns a list, as follows:

    Arrays.asList(new Data(10), new Data(20))

The calculateSum method in BusinessServiceImpl calculates the sum 10+20 and returns 30.

We will assert for 30 in the test method using assertEquals:

    long sum = service.calculateSum(DUMMY_USER); 
assertEquals(30, sum);

The complete code of the test is as follows; it has one test method:

    @RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = {"/BusinessApplicationContext.xml" })
public class BusinessServiceJavaContextTest {

private static final User DUMMY_USER = new User("dummy");

@Autowired
private BusinessService service;

@Test
public void testCalculateSum() {
long sum = service.calculateSum(DUMMY_USER);
assertEquals(30, sum);
}

}

One of the important things to remember is the preceding test is not really a unit test. The test for BusinessServiceImpl is using the actual implementation of DataServiceImpl. If DataServiceImpl was retrieving data from the database, then the test would depend on the data present in the database.

The question now is this: how do we unit test BusinessServiceImpl without using a real implementation of DataService?

There are two options:

  • Create a stub implementation of the data service, in the src estjava folder, providing some dummy data. Use a separate test context configuration to autowire the stub implementation instead of the real DataServiceImpl class.
  • Create a mock of DataService and autowire the mock into BusinessServiceImpl.

Creating a stub implementation would mean the creation of an additional class and an additional context. Stubs become more difficult to maintain, as we need more variations in data for the unit test.

In the next section, we will explore the second option of using a mock for unit testing. With the evolution of mocking frameworks (especially Mockito) in the last few years, you will see that we would not even need to launch a Spring context to execute the unit test.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset