My current team maintains an application built using Spring and Kotlin. We have several thousand unit and integration tests. I'm a big fan of condensing code as much as possible, so long as it remains legibile. A lot of our older integration tests in particular take the following form:
@ExtendWith(SpringExtension::class)
class SomethingIntTest : TestBase() {
@Autowired
private lateinit var mockMvc: MockMvc
@Autowired
private lateinit var userHelper: UserHelper
@Autowired
private lateinit var somethingService: SomethingService
@BeforeEach
public override fun setup() {
super.setup()
//...
}
Using default Kotlin formatting, the dependencies for the tests take up 3 lines each. This could be condensed by eliminating the empty lines, and possibly putting the @Autowired
annotation on each line. But, there is another way to accomplish the same: constructor injection. Constructor injection isn't just limited to the production code, it can be employed in tests as well.
@ExtendWith(SpringExtension::class)
class SomethingIntTest @Autowired constructor(
private val mockMvc: MockMvc
private val userHelper: UserHelper
private val somethingService: SomethingService
): TestBase() {
@BeforeEach
public override fun setup() {
super.setup()
//...
}
Not only does this take up less vertical space - half the number of lines in this example - it also accomplishes one other thing. These dependencies are now immutable, made possible by dropping the lateinit var
that is required for field injection, and replacing it with val
.