Introduction to Testing in Java: Dependencies

Welcome to Part 5 of this review of the Pluralsight course Introduction to Testing in Java by Richard Warburton.

Richard is an empirical technologist and solver of deep-dive technical problems and works independently as a Software Engineer and Trainer. He’s the author of Java 8 Lambdas and a trainer on java8training.com.

He’s a leader in the London Java Community, has a set on the JCP and runs Java Hackdays, and has given talks at Devoxx, JavaOne, JFokus, Geecon, Oredev, JAX London, and Codemotion. He obtained a PhD in Computer Science from The University of Warwick.

Also in this series:

Part 1 – Introduction
Part 2 – Testing Code
Part 3 – Writing Good Tests
Part 4 – Test Driven Development
Part 5 – Dependencies

Dependencies

Richard defines a dependency as:

“A relationship between two components where the functionality of one component relies on another component”

As an example of this we have a sales report with three components: Report, AnalysisService and CsvRepository

Report is dependent on the AnalysisService, and AnalysisService is dependent on the CsvRepository.

Richard explains there are two problems with this:
1. Lack of isolation
2. Coupling

Dependency Injection

This is a way to resolve the coupling issues that the sales report has. Richard says it’s

“A $20 term for a 20 cent concept”

We look at constructor injection in this module, and this is the most common way of doing dependency injection.

Dependency Injection (Live Coding)

We see the Sales Report application and Richard talks us through its classes:

– SimpleReportRunner.java
– SalesAnalysisService.java
– SalesReport.java

We refactor this to use constructor injection, and create a SalesRepository interface which CsvSalesRepository implements.

The code still behaves the same as before, but we now have better separation of concerns, looser coupling, and the code is easier to test.

Test Doubles

crash-testing-dummies

We use test doubles instead of the real implementations that our class under test is dependent on. There are several types on Test Double:

– Fake: working implementation but much simpler than a real one
– Stub: a ready-made answer to method calls
– Mock: Tests the interactions with the object

(In JavaScript and probably some other languages, there are also Spies)

See Martin Fowler’s classic article mocks aren’t stubs

Also see Alex Zhukovich’s Android testing: Mockito and Robolectric

Test Doubles (Live Coding)

The code here is Java 8, so if you’re confused see the “What’s New in Java 8” course.

The first test is shouldAggregateStoreSales, and we use our own hand-made stubRepo as our SalesRepository stub.

However Richard says as things get more complicated it’s better for as to use a library such as Mockito.

We refactor this test to use Mockito and first find it returns an empty list as a stub, which isn’t what we want.

We need to tell Mockito the value we want for our stub:

Mockito.when(stubRepo.loadSales()).thenReturn(exampleSales);

We can make this code terser by right clicking on the Mockito methods by adding static imports.

For example we can right click on Mockito.mock and choose
“Add static import for ‘org.mockito.Mockito.mock'”

Mockito also has a verify method and Richard shows us we can use this to verify our tallyStores method has called loadSales:

verify(mockRepo).loadSales();

Appendix 1: Spring

This is a brief look at the Spring DI framework. Richard says it’s “not a simple beast” and if you need to learn it in detail you should watch the Spring Fundamentals course by Bryan Hansen.

The advantage over using Spring over hand-written dependency injection is the Spring framework offers a lot of functionality.

Richard says it’s overkill for simple applications but useful for more complex ones and is the most commonly used DI framework for Java.

Appendix 2: Guice

Guice (pronounced ‘Juice’) is a lightweight DI framework for Java written by Google.
It has good documentation available on Github.

Again it doesn’t do anything that we can’t do by hand, but can simplify Inversion of Control for us once we’ve learnt it by reducing boilerplate code.

We use modules here, which are like recipes of telling Guice how to build an object graph. We also use a DSL syntax for binding classes and instances.

bind(String.class)
.annotatedWith(Names.named("fileLocation"))
.toInstance(fileLocation);

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s