Injection

Installation

If you are using maven, you can add following dependency to your project.

01
02
03
04
05
06
<dependency>
    <groupId>org.unitils</groupId>
    <artifactId>unitils-inject</artifactId>
    <version>3.4.2</version>
    <scope>test</scope>
</dependency>

If you are not using maven you can download the unitils-with-dependencies.zip. The required jar, unitils-inject.jar, can be found in the unitils-inject folder, the required dependencies, in the unitils-inject/lib folder.

Injecting objects

Unitils offers some utility methods to do injection of objects such as mocks into a target object (e.g. the tested object). There does not have to be any setter method, the fields can be private and can even be static.

Marking the tested object

The tested object is the actual instance that is being tested. The field of this tested object can be annotated with an TestedObject annotation. This will then become the default target for the injection. Unitils will automatically create an instance of the tested object if no instance is explicitly created in your test.

01
02
03
04
05
06
public class MyServiceTest extends UnitilsJUnit4 {
 
    @TestedObject
    private MyService myService;
 
}

In this example we're writing a test for MyService. The test is unitils-enabled (it extends UnitilsJUnit4) so that unitils will handle the annotations. The field that holds the myService instance that is going to be used in the tests is marked as TestedObject. Unitils will automatically create a new MyService instance and will use it as default target for the injection annotations (see below). If you do not want unitils to create the instance, you can always create the instance yourself.

Note that you're not required to use the TestedObject annotation, all the injection methods and annotations offer the possibility to explicitly specify the target object.

Injecting into a named property

01
02
03
04
05
06
07
08
09
public class MyServiceTest extends UnitilsJUnit4 {
 
    @TestedObject
    private MyService myService;
 
    @InjectInto(property = "myDaoField")
    private MyDao myDao;
 
}

This will inject the myDao value into a field named myDaoField of the tested object, myService. Unitils injects the value directly in the field, there does not have to be a setter and the field can be private. The value for the attribute property of @Inject can be an arbitrary OGNL expression.

Instead of using a tested object, you can also specify the target object explicitly:

01
02
03
04
05
06
07
08
public class MyServiceTest extends UnitilsJUnit4 {
 
    private MyService myService;
 
    @InjectInto(target = "myService", property = "myDaoField")
    private MyDao myDao;
 
}

Injection by type

01
02
03
04
05
06
07
08
09
public class MyServiceTest extends UnitilsJUnit4 {
 
    @TestedObject
    private MyService myService;
 
    @InjectIntoByType
    private MyDao myDao;
 
}

This will inject the myDao value into a field of type MyDao of the tested object, myService. There is no need to name the actual field, unitils will look for the best matching field type. If there are multiple possible targets, an exception will be raised. You will then have to use the InjectInto and explicitly name the property instead.

As with the InjectInto annotation you can also specify the target object explicitly:

01
02
03
04
05
06
07
08
public class MyServiceTest extends UnitilsJUnit4 {
 
    private MyService myService;
 
    @InjectIntoByType(target = "myService")
    private MyDao myDao;
 
}

Static injection into a named property

01
02
03
04
05
06
public class MyServiceTest extends UnitilsJUnit4 {
 
    @InjectIntoStatic(target = MyService.class, property = "myDaoSingleton")
    private MyDao myDao;
 
}

This will inject the myDao value into the static myDaoSingleton field of the MyService class. After the test the value of the field will automatically be reset to its old value. This avoids that subsequent tests use the value that was set by this tests (it's a static field).

Following restores actions are possible:

  • old value (default): put back the original value
  • no restore: do nothing, leave the injected value
  • null or 0 value: set the static field to null for objects or 0 for primitives

The restore action can be specified in the annotation.

01
02
03
04
05
06
07
08
@InjectIntoStatic(target = MyService.class, property = "myDaoSingleton", restore = OLD_VALUE)
private MyDao myDao1;
 
@InjectIntoStatic(target = MyService.class, property = "myDaoSingleton", restore = NO_RESTORE)
private MyDao myDao2;
 
@InjectIntoStatic(target = MyService.class, property = "myDaoSingleton", restore = NULL_OR_0_VALUE)
private MyDao myDao3;

If no restore action is specified, the default, old value, will be used. This default is configurable by setting following property:

01
02
# The default restore behavior. Possible values: old_value, no_restore or null_or_0_value
InjectModule.InjectIntoStatic.Restore.default=old_value

Injection example with mocks

In this example, we create a mock of type MyDao and inject it in the tested object MyService. Because the test does not create the myService instance, it will be automatically created by unitils.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
public class MyServiceInjectTest extends UnitilsJUnit4 {
 
    @TestedObject
    private MyService myService;
 
    @InjectIntoByType
    private Mock<MyDao> myDaoMock;
 
    @Test
    public void testMethod() {
        // define behavior
        myDaoMock.returns("something").getSomething();
 
        // do the actual test
        boolean result = myService.doService();
 
        // assert results and invocations
        assertTrue(result);
        myDaoMock.assertInvoked().storeSomething("something");
    }
}