If testing is hard, inject what you need to verify
When you have a hard time testing something, the solution is usually to inject the thing you would like to verify.
Suppose we are starting to implement a Car
class that stores passengers by their name.
class Car {
private val passengers: MutableSet<String> = HashSet()
fun storePassenger(name: String) {
passengers.add(name)
}
}
How to test that the method storePassenger(name: String)
stores a name into the passengers
set?
The typical solution is to define another method in Car
to check if it contains a passenger.
class Car {
private val passengers: MutableSet<String> = HashSet()
fun storePassenger(name: String) {
passengers.add(name)
}
fun containsPassenger(name: String): Boolean {
return passengers.contains(name)
}
}
So we can write the following test
@Test
fun `stores the names of the passengers`() {
val car = Car()
car.storePassenger("Andrea")
assertTrue(passengers.containsPassenger("Andrea"))
}
However, this is already a disappointment because we are forced to write a public method just for the sake of testing.
Moreover, what if by specifications we must prevent any other code to query Car
about its passengers?
The solution can be to inject the passengers
set a construction time.
class Car(private val passengers: MutableSet<String>) {
fun storePassenger(name: String) {
passengers.add(name)
}
}
Now we can test like follows.
@Test
fun `stores the names of the passengers`() {
val passengers = HashSet()
val car = Car(passengers)
car.storePassenger("Andrea")
assertTrue(passengers.contains("Andrea"))
}
By injecting the passengers
set we can get rid of the useless containsPassenger
method. Furthermore, we have now the
opportunity to make our code more modular, making Car
independent of the data structure used to store the passengers.
For this, we can use MutableCollection<String>
instead of MutableSet<String>
class Car(private val passengers: MutableCollection<String>) {
fun storePassenger(name: String) {
passengers.add(name)
}
}
Recommended reads
Teach me back
I really appreciate any feedback about the book and my current understanding of software design.