Posts Tagged ‘Dependency Injection’

Direct field dependency injection

Saturday, July 19th, 2008

At almost any project i have been on there was a discussion whether to use constructor or setter injection. Sometimes it tends to be a religious war between developers and either side has good arguments for both approaches. With constructor injection you make sure that all dependencies are available on creation time of the object. Setter injection on the other hand gives you a little bit more flexibility. Especially if a class has more than 3 constructor parameters it’s getting a bit clunky with constructor injection.
I personally tend more to constructor injection but since the auto-wiring capabilities of the Spring frameworks there is a third way to do your dependency injection: inject a dependency directly into the field of a class. Of course this approach has a downside if the class is used outside the Spring container, but for most Spring-based projects this is quite unlikely. Let’s look at some code to see how field injection works.

@Service
public class HelloService {
 
    public String sayHello() {
        return "Hello! I'm a service";
    }
}
 
@Component
public class SomeComponent {
 
    @Autowired
    private HelloService service;
 
    public String saySomething() {
        return service.sayHello();
    }
}

It’s as simple as that. The classes are annotated with @Service and @Component to be considered as candidates for auto-detection as i prefer to have as little XML configuration as possible. Thus the applicationContext.xml is quite simple:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd">
 
    <context:annotation-config/>
    <context:component-scan base-package="org.playground.di"/>
</beans>

Of course we usually would start out by writing tests first. But how can we write unit tests for SomeComponent when we don’t have access to the field and inject a mock object? Luckily the developers of Spring thought of that and provide us with a class called ReflectionTestUtils which is available since Spring 2.5. For this unit test i’ll use Mockito to mock out HelloService.

public class SomeComponentUnitTest {
 
    @Mock
    private HelloService mockService;
 
    @Before
    public void initMocks() {
        MockitoAnnotations.initMocks(this);
    }
 
    @Test
    public void shouldUseMockService() {
 
        SomeComponent component = new SomeComponent();
        ReflectionTestUtils.setField(component, "service", mockService);
 
        String expectedMessage = "I'm from a mock";
        Mockito.stub(mockService.sayHello()).toReturn(expectedMessage);
 
        String actualMessage = component.saySomething();
 
        verify(mockService).sayHello();
 
        Assert.assertEquals(actualMessage, expectedMessage);
    }
}

To complete our testing we also gonna write an integration test:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public class SomeComponentIntegrationTest {
 
    @Autowired
    private SomeComponent consumer;
 
    @Test
    public void shouldSaySomething() {
 
        String expectedMessage = "Hello! I'm a service";
 
        String actualMessage = consumer.saySomething();
 
        Assert.assertEquals(expectedMessage, actualMessage);
    }
}