From 337cb798e82e52283f8c569f64cc2d34a6a64bea Mon Sep 17 00:00:00 2001 From: Johannes Spangenberg Date: Sat, 3 Sep 2022 16:25:29 +0200 Subject: [PATCH] fixup! Fixes #2626 : Introduce MockSettings.mockMaker --- src/main/java/org/mockito/Mock.java | 6 +++++ src/main/java/org/mockito/MockMakers.java | 27 +++++++++++++++++++ src/main/java/org/mockito/MockSettings.java | 20 ++++++++++++++ src/main/java/org/mockito/Mockito.java | 23 +++++++++++++--- .../mockito/mock/MockCreationSettings.java | 7 +++-- .../java/org/mockito/plugins/MockMaker.java | 4 +-- 6 files changed, 80 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/mockito/Mock.java b/src/main/java/org/mockito/Mock.java index 72477a9278..0fa31fcc44 100644 --- a/src/main/java/org/mockito/Mock.java +++ b/src/main/java/org/mockito/Mock.java @@ -13,6 +13,7 @@ import java.lang.annotation.Target; import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.plugins.MockMaker; import org.mockito.stubbing.Answer; /** @@ -124,6 +125,11 @@ */ Strictness strictness() default Strictness.TEST_LEVEL_DEFAULT; + /** + * Mock will be created by the given {@link MockMaker}, see {@link MockSettings#mockMaker(String)}. + * + * @since ${NEXT_VERSION} + */ String mockMaker() default ""; enum Strictness { diff --git a/src/main/java/org/mockito/MockMakers.java b/src/main/java/org/mockito/MockMakers.java index c21eaa374e..347a9efb7e 100644 --- a/src/main/java/org/mockito/MockMakers.java +++ b/src/main/java/org/mockito/MockMakers.java @@ -4,9 +4,36 @@ */ package org.mockito; +import org.mockito.plugins.MockMaker; + +/** + * Constants for built-in implementations of {@code MockMaker}. + * You may use the constants of this class for {@link MockSettings#mockMaker(String)} or {@link Mock#mockMaker()}. + * The string values of these constants may also be used in the resource file mockito-extensions/org.mockito.plugins.MockMaker + * as described in the class documentation of {@link MockMaker}. + * + * @since ${NEXT_VERSION} + */ public final class MockMakers { + /** + * Inline mock maker which can mock final types, enums and final methods. + * This mock maker cannot mock native methods, + * and it does not support {@link MockSettings#extraInterfaces(Class[]) extra interfaces}. + * + * @see Mocking final types, enums and final methods + */ public static final String INLINE = "mock-maker-inline"; + /** + * Proxy mock maker which avoids code generation, but can only mock interfaces. + * + * @see Avoiding code generation when restricting mocks to interfaces + */ public static final String PROXY = "mock-maker-proxy"; + /** + * Subclass mock maker which mocks types by creating subclasses. + * This is the first built-in mock maker which has been provided by Mockito. + * Since this mock maker relies on subclasses, it cannot mock final classes and methods. + */ public static final String SUBCLASS = "mock-maker-subclass"; private MockMakers() {} diff --git a/src/main/java/org/mockito/MockSettings.java b/src/main/java/org/mockito/MockSettings.java index 6058159618..efb1c03e66 100644 --- a/src/main/java/org/mockito/MockSettings.java +++ b/src/main/java/org/mockito/MockSettings.java @@ -15,6 +15,7 @@ import org.mockito.listeners.VerificationStartedListener; import org.mockito.mock.MockCreationSettings; import org.mockito.mock.SerializableMode; +import org.mockito.plugins.MockMaker; import org.mockito.quality.Strictness; import org.mockito.stubbing.Answer; @@ -382,5 +383,24 @@ public interface MockSettings extends Serializable { */ MockSettings strictness(Strictness strictness); + /** + * Specifies the {@code MockMaker} for the mock. + * The default depends on your project as described in the class documentation of {@link MockMaker}. + * You should usually use the default, this option primarily exists to ease migrations. + * You may specify either one of the constants from {@link MockMakers}, + *
+     *     Object mock = Mockito.mock(Object.class, Mockito.withSettings()
+     *             .mockMaker(MockMakers.INLINE));
+     * 
+ * or the {@link Class#getName() binary name} of a class which implements the {@code MockMaker} interface. + *
+     *     Object mock = Mockito.mock(Object.class, Mockito.withSettings()
+     *             .mockMaker("org.awesome.mockito.AwesomeMockMaker"));
+     * 
+ * + * @param mockMaker the {@code MockMaker} to use for the mock + * @return settings instance so that you can fluently specify other settings + * @since ${NEXT_VERSION} + */ MockSettings mockMaker(String mockMaker); } diff --git a/src/main/java/org/mockito/Mockito.java b/src/main/java/org/mockito/Mockito.java index 9f7383f232..16659ab29f 100644 --- a/src/main/java/org/mockito/Mockito.java +++ b/src/main/java/org/mockito/Mockito.java @@ -105,7 +105,8 @@ * 49. New API for mocking object construction (Since 3.5.0)
* 50. Avoiding code generation when restricting mocks to interfaces (Since 3.12.2)
* 51. New API for marking classes as unmockable (Since 4.1.0)
- * 52. New strictness attribute for @Mock annotation and MockSettings.strictness() methods (Since 4.6.0)
+ * 52. New strictness attribute for @Mock annotation and MockSettings.strictness() methods (Since 4.6.0)
+ * 53. Specifying mock maker for individual mocks (Since ${NEXT_VERSION})
* * *

0. Migrating to Mockito 2

@@ -1586,7 +1587,7 @@ * released. To define mock behavior and to verify method invocations, use the MockedConstruction that is returned. *

* - *

50. Avoiding code generation when only interfaces are mocked (since 3.12.2)

+ *

50. Avoiding code generation when only interfaces are mocked (since 3.12.2)

* * The JVM offers the {@link java.lang.reflect.Proxy} facility for creating dynamic proxies of interface types. For most applications, Mockito * must be capable of mocking classes as supported by the default mock maker, or even final classes, as supported by the inline mock maker. To @@ -1609,7 +1610,7 @@ *

* *

52. - * New strictness attribute for @Mock annotation and MockSettings.strictness() methods (Since 4.6.0)

+ * New strictness attribute for @Mock annotation and MockSettings.strictness() methods (Since 4.6.0) * * You can now customize the strictness level for a single mock, either using `@Mock` annotation strictness attribute or * using `MockSettings.strictness()`. This can be useful if you want all of your mocks to be strict, @@ -1622,6 +1623,22 @@ * Foo mock = Mockito.mock(Foo.class, withSettings().strictness(Strictness.WARN)); * * + *

53. + * Specifying mock maker for individual mocks (Since ${NEXT_VERSION})

+ * + * You may encounter situations where you want to use a different mock maker for a specific test only. + * For example, you might want to migrate to the inline mock maker, but a few test do not work right away. + * In such case, you can (temporarily) use {@link MockSettings#mockMaker(String)} and {@link Mock#mockMaker()} + * to specify the mock maker for a specific mock which is causing the problem. + * + *

+ *   // using annotation
+ *   @Mock(mockMaker = MockMakers.SUBCLASS)
+ *   Foo mock;
+ *   // using MockSettings.withSettings()
+ *   Foo mock = Mockito.mock(Foo.class, withSettings().mockMaker(MockMakers.SUBCLASS));
+ * 
+ * */ @CheckReturnValue @SuppressWarnings("unchecked") diff --git a/src/main/java/org/mockito/mock/MockCreationSettings.java b/src/main/java/org/mockito/mock/MockCreationSettings.java index f4ef689ea6..fbda3f0e5a 100644 --- a/src/main/java/org/mockito/mock/MockCreationSettings.java +++ b/src/main/java/org/mockito/mock/MockCreationSettings.java @@ -138,8 +138,11 @@ public interface MockCreationSettings { Strictness getStrictness(); /** - * The {@link MockMaker} which shall by used instead of the default. When - * the return value is {@code null}, the default shall be used. + * Returns the {@link MockMaker} which shall be used to create the mock. + * When the return value is {@code null}, the default shall be used. + * + * @see MockSettings#mockMaker(String) + * @since ${NEXT_VERSION} */ String getMockMaker(); } diff --git a/src/main/java/org/mockito/plugins/MockMaker.java b/src/main/java/org/mockito/plugins/MockMaker.java index b2d0be668c..c0b1cbcd2d 100644 --- a/src/main/java/org/mockito/plugins/MockMaker.java +++ b/src/main/java/org/mockito/plugins/MockMaker.java @@ -51,10 +51,10 @@ *

If you want to use a {@code MockMaker} only for a specific mock, * you can specify it using {@link MockSettings#mockMaker(String)}.

*
- *     // Use a mockmaker shipping with Mockito
+ *     // Use a built-in mock maker
  *     Object mock = Mockito.mock(Object.class, Mockito.withSettings()
  *             .mockMaker(MockMakers.INLINE));
- *     // Or load a mockmaker using a fully qualified class name
+ *     // Or load a mock maker using a fully qualified class name
  *     Object mock = Mockito.mock(Object.class, Mockito.withSettings()
  *             .mockMaker("org.awesome.mockito.AwesomeMockMaker"));
  *