From 6d3d3d11c4fe02d9e78dbfe2c10b7b554ebe6e17 Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Thu, 26 Mar 2026 14:28:36 +0100 Subject: [PATCH] =?UTF-8?q?Introduce=20Kotlin=20examples=20for=20Bean=20Ov?= =?UTF-8?q?errides=20(@=E2=81=A0MockitoBean,=20etc.)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit introduces Kotlin examples in the reference manual for @⁠MockitoBean, @⁠MockitoSpyBean, and @⁠TestBean. Closes gh-36541 --- .../annotation-mockitobean.adoc | 143 ++++++++++++++++++ .../annotation-testbean.adoc | 43 ++++++ 2 files changed, 186 insertions(+) diff --git a/framework-docs/modules/ROOT/pages/testing/annotations/integration-spring/annotation-mockitobean.adoc b/framework-docs/modules/ROOT/pages/testing/annotations/integration-spring/annotation-mockitobean.adoc index 2b072e8b0e5..b0ad7707ff3 100644 --- a/framework-docs/modules/ROOT/pages/testing/annotations/integration-spring/annotation-mockitobean.adoc +++ b/framework-docs/modules/ROOT/pages/testing/annotations/integration-spring/annotation-mockitobean.adoc @@ -140,6 +140,21 @@ Java:: } ---- <1> Replace the bean with type `CustomService` with a Mockito mock. + +Kotlin:: ++ +[source,kotlin,indent=0,subs="verbatim,quotes"] +---- + @SpringJUnitConfig(TestConfig::class) + class BeanOverrideTests { + + @MockitoBean // <1> + lateinit var customService: CustomService + + // tests... + } +---- +<1> Replace the bean with type `CustomService` with a Mockito mock. ====== In the example above, we are creating a mock for `CustomService`. If more than one bean @@ -168,6 +183,22 @@ Java:: } ---- <1> Replace the bean named `service` with a Mockito mock. + +Kotlin:: ++ +[source,kotlin,indent=0,subs="verbatim,quotes"] +---- + @SpringJUnitConfig(TestConfig::class) + class BeanOverrideTests { + + @MockitoBean("service") // <1> + lateinit var customService: CustomService + + // tests... + + } +---- +<1> Replace the bean named `service` with a Mockito mock. ====== The following `@SharedMocks` annotation registers two mocks by-type and one mock by-name. @@ -187,6 +218,19 @@ Java:: ---- <1> Register `OrderService` and `UserService` mocks by-type. <2> Register `PrintingService` mock by-name. + +Kotlin:: ++ +[source,kotlin,indent=0,subs="verbatim,quotes"] +---- + @Target(AnnotationTarget.CLASS) + @Retention(AnnotationRetention.RUNTIME) + @MockitoBean(types = [OrderService::class, UserService::class]) // <1> + @MockitoBean(name = "ps1", types = [PrintingService::class]) // <2> + annotation class SharedMocks +---- +<1> Register `OrderService` and `UserService` mocks by-type. +<2> Register `PrintingService` mock by-name. ====== The following demonstrates how `@SharedMocks` can be used on a test class. @@ -217,6 +261,34 @@ Java:: ---- <1> Register common mocks via the custom `@SharedMocks` annotation. <2> Optionally inject mocks to _stub_ or _verify_ them. + +Kotlin:: ++ +[source,kotlin,indent=0,subs="verbatim,quotes"] +---- + @SpringJUnitConfig(TestConfig::class) + @SharedMocks // <1> + class BeanOverrideTests { + + @Autowired + lateinit var orderService: OrderService // <2> + + @Autowired + lateinit var userService: UserService // <2> + + @Autowired + lateinit var ps1: PrintingService // <2> + + // Inject other components that rely on the mocks. + + @Test + fun testThatDependsOnMocks() { + // ... + } + } +---- +<1> Register common mocks via the custom `@SharedMocks` annotation. +<2> Optionally inject mocks to _stub_ or _verify_ them. ====== TIP: The mocks can also be injected into `@Configuration` classes or other test-related @@ -246,6 +318,21 @@ Java:: } ---- <1> Wrap the bean with type `CustomService` with a Mockito spy. + +Kotlin:: ++ +[source,kotlin,indent=0,subs="verbatim,quotes"] +---- + @SpringJUnitConfig(TestConfig::class) + class BeanOverrideTests { + + @MockitoSpyBean // <1> + lateinit var customService: CustomService + + // tests... + } +---- +<1> Wrap the bean with type `CustomService` with a Mockito spy. ====== In the example above, we are wrapping the bean with type `CustomService`. If more than @@ -271,6 +358,21 @@ Java:: } ---- <1> Wrap the bean named `service` with a Mockito spy. + +Kotlin:: ++ +[source,kotlin,indent=0,subs="verbatim,quotes"] +---- + @SpringJUnitConfig(TestConfig::class) + class BeanOverrideTests { + + @MockitoSpyBean("service") // <1> + lateinit var customService: CustomService + + // tests... + } +---- +<1> Wrap the bean named `service` with a Mockito spy. ====== The following `@SharedSpies` annotation registers two spies by-type and one spy by-name. @@ -290,6 +392,19 @@ Java:: ---- <1> Register `OrderService` and `UserService` spies by-type. <2> Register `PrintingService` spy by-name. + +Kotlin:: ++ +[source,kotlin,indent=0,subs="verbatim,quotes"] +---- + @Target(AnnotationTarget.CLASS) + @Retention(AnnotationRetention.RUNTIME) + @MockitoSpyBean(types = [OrderService::class, UserService::class]) // <1> + @MockitoSpyBean(name = "ps1", types = [PrintingService::class]) // <2> + annotation class SharedSpies +---- +<1> Register `OrderService` and `UserService` spies by-type. +<2> Register `PrintingService` spy by-name. ====== The following demonstrates how `@SharedSpies` can be used on a test class. @@ -320,6 +435,34 @@ Java:: ---- <1> Register common spies via the custom `@SharedSpies` annotation. <2> Optionally inject spies to _stub_ or _verify_ them. + +Kotlin:: ++ +[source,kotlin,indent=0,subs="verbatim,quotes"] +---- + @SpringJUnitConfig(TestConfig::class) + @SharedSpies // <1> + class BeanOverrideTests { + + @Autowired + lateinit var orderService: OrderService // <2> + + @Autowired + lateinit var userService: UserService // <2> + + @Autowired + lateinit var ps1: PrintingService // <2> + + // Inject other components that rely on the spies. + + @Test + fun testThatDependsOnMocks() { + // ... + } + } +---- +<1> Register common spies via the custom `@SharedSpies` annotation. +<2> Optionally inject spies to _stub_ or _verify_ them. ====== TIP: The spies can also be injected into `@Configuration` classes or other test-related diff --git a/framework-docs/modules/ROOT/pages/testing/annotations/integration-spring/annotation-testbean.adoc b/framework-docs/modules/ROOT/pages/testing/annotations/integration-spring/annotation-testbean.adoc index b752becaaa9..e7192604ef2 100644 --- a/framework-docs/modules/ROOT/pages/testing/annotations/integration-spring/annotation-testbean.adoc +++ b/framework-docs/modules/ROOT/pages/testing/annotations/integration-spring/annotation-testbean.adoc @@ -73,6 +73,27 @@ Java:: ---- <1> Mark a field for overriding the bean with type `CustomService`. <2> The result of this static method will be used as the instance and injected into the field. + +Kotlin:: ++ +[source,kotlin,indent=0,subs="verbatim,quotes"] +---- + class OverrideBeanTests { + @TestBean // <1> + lateinit var customService: CustomService + + // test case body... + + companion object { + @JvmStatic + fun customService(): CustomService { // <2> + return MyFakeCustomService() + } + } + } +---- +<1> Mark a field for overriding the bean with type `CustomService`. +<2> The result of this static method will be used as the instance and injected into the field. ====== In the example above, we are overriding the bean with type `CustomService`. If more than @@ -102,6 +123,28 @@ Java:: <1> Mark a field for overriding the bean with name `service`, and specify that the factory method is named `createCustomService`. <2> The result of this static method will be used as the instance and injected into the field. + +Kotlin:: ++ +[source,kotlin,indent=0,subs="verbatim,quotes"] +---- + class OverrideBeanTests { + @TestBean(name = "service", methodName = "createCustomService") // <1> + lateinit var customService: CustomService + + // test case body... + + companion object { + @JvmStatic + fun createCustomService(): CustomService { // <2> + return MyFakeCustomService() + } + } + } +---- +<1> Mark a field for overriding the bean with name `service`, and specify that the + factory method is named `createCustomService`. +<2> The result of this static method will be used as the instance and injected into the field. ====== [TIP]