Book Image

Mockito for Spring

By : Sujoy Acharya
Book Image

Mockito for Spring

By: Sujoy Acharya

Overview of this book

Table of Contents (12 chapters)
Mockito for Spring
Credits
About the Author
About the Reviewers
www.PacktPub.com
Preface
Index

Learning the Inversion of Control


Inversion of Control (IoC) and dependency injection (DI) are used interchangeably. IoC is achieved through DI. DI is the process of providing dependencies and IoC is the end result of DI. Spring's IoC container enforces the DI pattern for your components, and this leaves them loosely coupled and allows you to code to abstractions.

Dependency injection is a style of object configuration in which an object's fields and collaborators are set by an external entity. In other words, objects are configured by an external entity. Dependency injection is an alternative to having the object configure itself. This might sound a bit vague, so let's look at a simple example.

After visiting the Packt Publishing website, you can search books by the author's name or different criteria. We'll look at the service that lists books by author.

The following interface defines book retrieval:

public interface BookService {
  List<Book> findAll();
}

The following class lists books by author names:

public class BookLister {

  private BookService bookFinder = new BookServiceImpl();
  
  public List<Book> findByAuthor(String author){
    List<Book> books = new ArrayList<>();
    
    for(Book aBook:bookFinder.findAll()){
      for(String anAuthor:aBook.getAuthors()){
        if(anAuthor.equals(author)){
          books.add(aBook);
          break;
        }
      }
    }
    
    return books;
  }
  
}

The BookLister class needs a BookService implementation; this means that the BookLister class depends on it. It cannot carry out its work without a BookService implementation. Therefore, BookLister has a dependency on the BookService interface and on some implementation of it. The BookLister class itself instantiates BookServiceImpl as its BookService implementation. Therefore, the BookLister class is said to satisfy its own dependencies. When a class satisfies its own dependencies, it automatically also depends on the classes it satisfies the dependencies with. In this case, BookLister now also depends on BookServiceImpl, and if any, on the other values passed as a parameter to the BookServiceImpl constructor. The BookService interface can have many implementations such as Spring JDBC-based data access and JPA-based data access implementation. We cannot use a different implementation of the BookService interface without changing the code.

To refactor this tight coupling, we can move the BookService instantiation to the constructor of the class. The following is the modified BookLister class:

public class BookLister {

  private final BookService bookFinder;
  
  public BookLister(BookService bookFinder) {
    this.bookFinder = bookFinder;
  }

  public List<Book> findByAuthor(String author){
    List<Book> books = new ArrayList<>();
    
    for(Book aBook:bookFinder.findAll()){
      for(String anAuthor:aBook.getAuthors()){
        if(anAuthor.equals(author)){
          books.add(aBook);
          break;
        }
      }
    }
    
    return books;
  }
  
}

Note that the BookService dependency is passed to the BookLister constructor as a constructor argument. Now, BookLister is only depending on BookService. Whoever instantiates the BookLister constructor will satisfy the dependency. The BookService dependency is said to be injected into the BookLister constructor, hence the term dependency injection. It is now possible to change the BookService implementation used by the BookLister class without changing the BookLister class.

There are two types of dependency injections:

  • Constructor injection

  • Setter injection

A Spring configuration file creates/defines and configures (resolves dependencies) beans. In the Spring configuration file, the constructor injection is constructed as follows:

<bean id="bookLister" class="com.packt.di.BookLister">
  <constructor-arg ref="bookService"/>
</bean>
<bean id="bookService" class="com.packt.di.BookServiceImpl" />

The preceding code is equivalent to the following:

BookService service = new BookServiceImpl();
BookLister bookLister = new BookLister(service);

The setter injection is carried out by setting a property. In a setter injection, instead of passing bookService as a constructor argument, we change the class to pass as a setter method argument.

The Spring configuration is as follows:

<bean id="bookListerSetterInjection" class="com.packt.di.BookLister">
   <property name="bookService" ref="bookService" />
</bean>
  
<bean id="bookService" class="com.packt.di.BookServiceImpl" />

The preceding code snippet is equivalent to the following:

BookService service = new BookServiceImpl();
BookLister bookLister = new BookLister();
bookLister.setBookService(service);

The Spring IoC container is known as ApplicationContext. The objects that are used in our application, defined in ApplicationContext, and managed by the Spring IoC container are called beans; for example, bookService is a bean.

A bean is an object that is managed by the Spring IoC container; beans are created with the configuration metadata that you supply to the container, such as in the form of XML <bean/> definitions or using Java annotations.

A bean definition describes a bean instance. The bean definition contains the information called configuration metadata, which is needed by the container to know how to create the bean, the life cycle of the bean, and the dependencies of the bean.

The following properties are used to define a bean:

  • class: This is mandatory and provides the fully qualified bean class name required for the container to create the bean instance.

  • name: This attribute (also known as id) uniquely identifies a bean.

  • scope: This provides the scope of the objects created from a bean definition, such as prototype and singleton. We'll learn about them later.

  • constructor-arg: This injects a dependency as a bean's constructor argument.

  • properties: This injects a dependency as a setter method argument.

  • lazy-init: If this is set as true, the IoC container creates the bean instance when it is first requested, rather than at startup, which means any configuration error is not discovered until the bean is eventually instantiated inside the Spring context.

  • init-method: This provides the method name of the bean that is being invoked just after all necessary properties on the bean are set by the IoC container. This is useful when we need to initialize/compute something after the bean is instantiated.

  • destroy-method: The container calls this method when the bean is destroyed; this is necessary when we need to clean up something before the bean is destroyed.

The following are the bean scopes:

  • singleton: A single instance of the bean per IoC container. This is not actually the same as in the singleton design pattern (that is, one instance per classloader).

  • prototype: A single bean definition to have any number of object instances. A new bean instance is created each time one is needed.

  • request: A bean instance per HTTP request, only valid in the web-aware application context.

  • session: A bean instance per HTTP session, only valid in the web-aware application context.

  • global-session: A bean instance per global HTTP session, only valid in the web-aware application context.

The following are the steps in a bean's life cycle:

  1. The first step is to find and instantiate the beans. The Spring IoC container reads the bean definitions from the XML and then instantiates them.

  2. The next step is to populate the bean properties and satisfy the dependencies. The IoC container uses dependency injection to set the properties.

  3. After setting the dependencies, the setBeanName method is invoked on the beans; if they implement the BeanNameAware interface, the setBeanName() method is invoked by passing the ID of the bean.

  4. After this, if a bean implements the BeanFactoryAware interface, the setBeanFactory() method is called with an instance of itself.

  5. The pre-initialization of BeanPostProcessor is done. If a bean has any BeanPostProcessor interface associated with it, the processBeforeInitialization() methods are called on the post processors.

  6. The init method is called; if a bean specifies an init-method, it will be called.

  7. Finally, the post-initialization is done; if there are any BeanPostProcessors associated with the bean, their postProcessAfterInitialization() methods are invoked.

Note that a POJO doesn't need to depend on anything Spring-specific. For particular cases, Spring provides hooks in the form of these interfaces. Using them means introducing a dependency on Spring. The following figure depicts the bean's life cycle:

To learn more about DI and IoC, visit the Martin Fowler site at http://martinfowler.com/articles/injection.html.