This title raises many questions, What is Pico container? What is Dependency Injection and why is it required, specifically what is its role in Automation Testing? Let us try answering each of these questions one by one.
Dependency Injection is a simple design pattern that allows us to develop loosely coupled code. This is achieved by decoupling the usage of an object from its creation. In other words, an object should not be created (using new keyword), in the same class as it is going to be used in. This means the objects will be created in some other class (Dependency) and will be injected to the class using them, hence called Dependency Injection.
Pico Containers can be used in cucumber and many other frameworks for Dependency injection via constructors. Pico is a light weight library that makes it easy to create an injector class which will instantiate all the required classes with their dependencies and will return those instances to the test class. Most important feature of Pico containers is to instantiate arbitrary objects.
Dependency Injection using Pico can commonly be achieved in three ways -
Constructor Injection - Dependency is injected to main class via its constructor. This approach is used when the main class cannot work without these dependencies.
Method Injection - Dependency is injected via a method. This is done when dependency needs to be renewed after each use.
Property Injection - Injection is done via a property ie. setter. This is done when dependency is selected or invoked at different places.
Similar to any other concept, DI also has its pros and cons.
Benefits of Dependency Injection -
Main class does not have to worry about how the objects will be created , Abstraction
Potential problems with DI -
Dependencies are resolved at runtime, so no compiler errors in case of any issues.
Debugging can be difficult in case of big projects.
Learning a framework with DI can sometimes be complex.
Dependency Injection in Test Automation
Now that we have some basic idea about Dependency Injection, let us try to understand its significance in Test Automation.
While working with Selenium, instantiating a WebDriver is the first step. This step will be repeated for each test file.
Page Object Model is another popular design pattern for Test Automation. As part of POM, a solution can have many page classes and each class will need to be instantiated for each test class.
Along with WebDriver and Page classes, there can be many other classes that require repeated instantiation in each test class, like test data readers, property file reader, database connections, logger classes etc.
So, to avoid tight coupling these classes and writing repeated code, it is a good idea to implement Dependency Injection. As the scope of these dependencies is across the class, Constructor injection seems appropriate here.
To solve above issue using Pico containers, we can create a class named TestContext as below (any name can be used).
Below are the Manager classes created for Page classes and reader classes, which are optional.
Modified test class with Dependency Injection can be as below -
As we can see here, all the required classes are instantiated in TestContext class and then returned to the test class in the constructor of test class. No new objects are created in the test class. Pico Containers can also be used to context or state sharing among steps of Cucumber scenarios.
In order to implement Pico Containers in cucumber test project, below dependency needs to be added to maven pom.xml.
And you are all set.