mockito-object-injection

Mockito Object Injection

License

License

Categories

Categories

Mockito Unit Testing
GroupId

GroupId

com.github.exabrial
ArtifactId

ArtifactId

mockito-object-injection
Last Version

Last Version

2.0.2
Release Date

Release Date

Type

Type

jar
Description

Description

mockito-object-injection
Mockito Object Injection
Project URL

Project URL

https://github.com/exabrial/mockito-object-injection
Source Code Management

Source Code Management

https://github.com/exabrial/mockito-object-injection/tree/master

Download mockito-object-injection

How to add to project

<!-- https://jarcasting.com/artifacts/com.github.exabrial/mockito-object-injection/ -->
<dependency>
    <groupId>com.github.exabrial</groupId>
    <artifactId>mockito-object-injection</artifactId>
    <version>2.0.2</version>
</dependency>
// https://jarcasting.com/artifacts/com.github.exabrial/mockito-object-injection/
implementation 'com.github.exabrial:mockito-object-injection:2.0.2'
// https://jarcasting.com/artifacts/com.github.exabrial/mockito-object-injection/
implementation ("com.github.exabrial:mockito-object-injection:2.0.2")
'com.github.exabrial:mockito-object-injection:jar:2.0.2'
<dependency org="com.github.exabrial" name="mockito-object-injection" rev="2.0.2">
  <artifact name="mockito-object-injection" type="jar" />
</dependency>
@Grapes(
@Grab(group='com.github.exabrial', module='mockito-object-injection', version='2.0.2')
)
libraryDependencies += "com.github.exabrial" % "mockito-object-injection" % "2.0.2"
[com.github.exabrial/mockito-object-injection "2.0.2"]

Dependencies

compile (1)

Group / Artifact Type Version
org.javassist : javassist jar 3.23.1-GA

provided (2)

Group / Artifact Type Version
org.junit.jupiter : junit-jupiter-api jar 5.6.2
org.mockito : mockito-core jar 3.5.0

Project Modules

There are no modules declared in this project.

Mockito Object Injection

Preamble

  • Mock testing leads to highly focused tests where every variable is controlled.
  • Dependency Injection + well structured programs + Mock testing = super clean codebase.

The problem is, how does one Mock a String, Boolean, or other final type if those types are being Injected?

Summary

This Junit Extension allows you to inject Strings (or any other object) into your @InjectMocks targets [objects under test] without booting a Spring, Weld, CDI, Arquillian, EJB, or other container. It's super lightweight, over 100,000x faster than booting Arquillian, and easy to use.

Example Problem

Take this Spring Controller (or if you're using the far superior and modern CDI framework, think @AppplicationScoped instead of @Controller and @Inject instead of @Autowired)

@Controller
public class MyController {
 @Value("securityEnabled")
 private Boolean securityEnabled;
 @Autowired
 private Authenticator auther;
 @Autowired
 private Logger log;

 public void doSomething() {
  if (securityEnabled) {
    auther.something();
  } else {
    log.warn("sec disabled");
  }
 }
}

If you wanted to write a true unit test* with no external dependencies, you'd probably want to use Mockito mock your dependencies:

@ExtendWith({ MockitoExtension.class })
class MyControllerTest {
 @InjectMocks
 private MyController myController;
 @Mock
 private Logger log;
 @Mock
 private Authenticator auther;
  
  @Test
  void testDoSomething() throws Exception {
   myController.doSomething();
   // results in NPE because myController.securityEnabled is null
  }
 }
  • Testing a "unit" of code is a unit test. In Java, typically a class is the smallest unit of code.

Example Solution

This JUnit5 extension allows you to arbitrarily set any field on your @InjectMocks [class under test] target. The injections happen very late; they happen when you call any non-private method on the class under test.

import com.github.exabrial.junit5.injectmap.InjectionMap;
import com.github.exabrial.junit5.injectmap.InjectMapExtension;

@TestInstance(Lifecycle.PER_CLASS)
@ExtendWith({ MockitoExtension.class, InjectExtension.class })
class MyControllerTest {
 @InjectMocks
 private MyController myController;
 @Mock
 private Logger log;
 @Mock
 private Authenticator auther;
 @InjectionSource
 private Boolean securityEnabled;
 
 @Test
 void testDoSomething_secEnabled() throws Exception {
  securityEnabled = Boolean.TRUE;
  myController.doSomething();
  // wahoo no NPE! Test the "if then" half of the branch
 }
 
 @Test 
 void testDoSomething_secDisabled() throws Exception {
  securityEnabled = Boolean.FALSE;
  myController.doSomething();
  // wahoo no NPE! Test the "if else" half of branch
 }
}

@PostConstruct invocation

CDI and SpringFramework allow the use of @PostConstruct. This is like a constructor, except the method annotated will be invoked after dependency injection is complete. This extension can be commanded to invoke the method annotated with @PostConstruct like so:

@ApplicationScoped
public class MyController {
 @Inject
 private Logger log; 
 
 @PostConstruct
 private void postConstruct() {
  log.info("initializing myController...");
  ... some initialization code
 }
}
@TestInstance(Lifecycle.PER_CLASS)
@ExtendWith({ MockitoExtension.class, InjectExtension.class })
class MyControllerTest {

 @InjectMocks
 @InvokePostConstruct
 // The postConstruct on this controller will be invoked
 private MyController myController;
 
 @Test
 void testSometing()

Ref: https://docs.oracle.com/javaee/7/api/javax/annotation/PostConstruct.html

License

All files are licensed Apache Source License 2.0. Please consider contributing any improvements you make back to the project.

Usage

Maven Coordinates:

<dependency>
 <groupId>org.junit.jupiter</groupId>
 <artifactId>junit-jupiter-api</artifactId>
 <version>5.6.2</version>
 <scope>test</scope>
</dependency>
<dependency>
 <groupId>org.mockito</groupId>
 <artifactId>mockito-core</artifactId>
 <version>3.5.0</version>
 <scope>test</scope>
</dependency>
<dependency>
 <groupId>com.github.exabrial</groupId>
 <artifactId>mockito-object-injection</artifactId>
 <version>2.0.2</version>
 <scope>test</scope>
</dependency>

The final note is that it should extraordinarily obvious that multithreading on the same test instances will cause problems. Set your forking policies accordingly to avoid race conditions.

Versions

Version
2.0.2
2.0.1
2.0.0
1.0.4
1.0.3
1.0.2
1.0.1
1.0.0