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
.