10000 Add support for customizing strictness via `@Mock` annotation and `Mo… · mockito/mockito@70cf2d2 · GitHub
[go: up one dir, main page]

Skip to content

Commit 70cf2d2

Browse files
Add support for customizing strictness via @Mock annotation and MockSettings (#2650)
Fixes #2648
1 parent 6ce278b commit 70cf2d2

File tree

13 files changed

+194
-7
lines changed

13 files changed

+194
-7
lines changed

src/main/java/org/mockito/Mock.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import java.lang.annotation.Target;
1414

1515
import org.mockito.junit.MockitoJUnitRunner;
16+
import org.mockito.quality.Strictness;
1617
import org.mockito.stubbing.Answer;
1718

1819
/**
@@ -105,10 +106,21 @@
105106
boolean serializable() default false;
106107

107108
/**
109+
* @deprecated Use {@link Mock#strictness()} instead.
110+
*
108111
* Mock will be lenient, see {@link MockSettings#lenient()}.
109112
* For examples how to use 'Mock' annotation and parameters see {@link Mock}.
110113
*
111114
* @since 2.23.3
112115
*/
116+
@Deprecated
113117
boolean lenient() default false;
118+
119+
/**
120+
* Mock will have custom strictness, see {@link MockSettings#strictness(Strictness)}.
121+
* For examples how to use 'Mock' annotation and parameters see {@link Mock}.
122+
*
123+
* @since 4.6.0
124+
*/
125+
Strictness strictness() default Strictness.STRICT_STUBS;
114126
}

src/main/java/org/mockito/MockSettings.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,8 @@ public interface MockSettings extends Serializable {
350350
<T> MockCreationSettings<T> buildStatic(Class<T> classToMock);
351351

352352
/**
353+
* @deprecated Use {@link MockSettings#strictness(Strictness)} instead.
354+
*
353355
* Lenient mocks bypass "strict 8000 stubbing" validation (see {@link Strictness#STRICT_STUBS}).
354356
* When mock is declared as lenient none of its stubbings will be checked for potential stubbing problems such as
355357
* 'unnecessary stubbing' ({@link UnnecessaryStubbingException}) or for 'stubbing argument mismatch' {@link PotentialStubbingProblem}.
@@ -360,5 +362,23 @@ public interface MockSettings extends Serializable {
360362
*
361363
* For more information and an elaborate example, see {@link Mockito#lenient()}.
362364
*/
365+
@Deprecated
363366
MockSettings lenient();
367+
368+
/**
369+
* Specifies strictness level for the mock.
370+
* The default strictness level is determined by the rule/runner used.
371+
* If you are using no rule/runner, the default strictness level is LENIENT
372+
*
373+
* <pre class="code"><code class="java">
374+
* Foo defaultStrictMock = mock(Foo.class);
375+
* Foo explicitStrictMock = mock(Foo.class, withSettings().strictness(Strictness.STRICT_STUBS));
376+
* Foo lenientMock = mock(Foo.class, withSettings().strictness(Strictness.LENIENT));
377+
* </code></pre>
378+
*
379+
* @param strictness the strictness level to set on mock
380+
* @return settings instance so that you can fluently specify other settings
381+
* @since 4.6.0
382+
*/
383+
MockSettings strictness(Strictness strictness);
364384
}

src/main/java/org/mockito/Mockito.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@
105105
* <a href="#49">49. New API for mocking object construction (Since 3.5.0)</a><br/>
106106
* <a href="#50">50. Avoiding code generation when restricting mocks to interfaces (Since 3.12.2)</a><br/>
107107
* <a href="#51">51. New API for marking classes as unmockable (Since 4.1.0)</a><br/>
108+
* <a href="#51">52. New strictness attribute for @Mock annotation and <code>MockSettings.strictness()</code> methods (Since 4.6.0)</a><br/>
108109
* </b>
109110
*
110111
* <h3 id="0">0. <a class="meaningful_link" href="#mockito2" name="mockito2">Migrating to Mockito 2</a></h3>
@@ -1606,6 +1607,21 @@
16061607
* For any class/interface you own that is problematic to mock, you can now mark the class with {@link org.mockito.DoNotMock @DoNotMock}. For usage
16071608
* of the annotation and how to ship your own (to avoid a compile time dependency on a test artifact), please see its JavaDoc.
16081609
* <p>
1610+
*
1611+
* <h3 id="52">52. <a class="meaningful_link" href="#mockito_strictness" name="mockito_strictness">
1612+
* New strictness attribute for @Mock annotation and <code>MockSettings.strictness()</code> methods (Since 4.6.0)</a></h3>
1613+
*
1614+
* You can now customize the strictness level for a single mock, either using `@Mock` annotation strictness attribute or
1615+
* using `MockSettings.strictness()`. This can be useful if you want all of your mocks to be strict,
1616+
* but one of the mocks to be lenient.
1617+
*
1618+
* <pre class="code"><code class="java">
1619+
* &#064;Mock(strictness = Strictness.LENIENT)
1620+
* Foo mock;
1621+
* // using MockSettings.withSettings()
1622+
* Foo mock = Mockito.mock(Foo.class, withSettings().strictness(Strictness.WARN));
1623+
* </code></pre>
1624+
*
16091625
*/
16101626
@CheckReturnValue
16111627
@SuppressWarnings("unchecked")

src/main/java/org/mockito/internal/configuration/MockAnnotationProcessor.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ public static Object processAnnotationForMock(
4545
if (annotation.stubOnly()) {
4646
mockSettings.stubOnly();
4747
}
48+
mockSettings.strictness(annotation.strictness());
4849
if (annotation.lenient()) {
4950
mockSettings.lenient();
5051
}

src/main/java/org/mockito/internal/creation/MockSettingsImpl.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import static org.mockito.internal.exceptions.Reporter.extraInterfacesRequiresAtLeastOneInterface;
1313
import static org.mockito.internal.exceptions.Reporter.methodDoesNotAcceptParameter;
1414
import static org.mockito.internal.exceptions.Reporter.requiresAtLeastOneListener;
15+
import static org.mockito.internal.exceptions.Reporter.strictnessDoesNotAcceptNullParameter;
1516
import static org.mockito.internal.util.collections.Sets.newSet;
1617

1718
import java.io.Serializable;
@@ -33,6 +34,7 @@
3334
import org.mockito.mock.MockCreationSettings;
3435
import org.mockito.mock.MockName;
3536
import org.mockito.mock.SerializableMode;
37+
import org.mockito.quality.Strictness;
3638
import org.mockito.stubbing.Answer;
3739

3840
@SuppressWarnings("unchecked")
@@ -239,7 +241,16 @@ public <T2> MockCreationSettings<T2> buildStatic(Class<T2> classToMock) {
239241

240242
@Override
241243
public MockSettings lenient() {
242-
this.lenient = true;
244+
this.strictness = Strictness.LENIENT;
245+
return this;
246+
}
247+
248+
@Override
249+
public MockSettings strictness(Strictness strictness) {
250+
this.strictness = strictness;
251+
if (strictness == null) {
252+
throw strictnessDoesNotAcceptNullParameter();
253+
}
243254
return this;
244255
}
245256

src/main/java/org/mockito/internal/creation/settings/CreationSettings.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import org.mockito.mock.MockCreationSettings;
1919
import org.mockito.mock.MockName;
2020
import org.mockito.mock.SerializableMode;
21+
import org.mockito.quality.Strictness;
2122
import org.mockito.stubbing.Answer;
2223

2324
public class CreationSettings<T> implements MockCreationSettings<T>, Serializable {
@@ -44,7 +45,7 @@ public class CreationSettings<T> implements MockCreationSettings<T>, Serializabl
4445
private boolean useConstructor;
4546
private Object outerClassInstance;
4647
private Object[] constructorArgs;
47-
protected boolean lenient;
48+
protected Strictness strictness = Strictness.STRICT_STUBS;
4849

4950
public CreationSettings() {}
5051

@@ -65,7 +66,7 @@ public CreationSettings(Creati 10000 onSettings copy) {
6566
this.useConstructor = copy.isUsingConstructor();
6667
this.outerClassInstance = copy.getOuterClassInstance();
6768
this.constructorArgs = copy.getConstructorArgs();
68-
this.lenient = copy.lenient;
69+
this.strictness = copy.strictness;
6970
this.stripAnnotations = copy.stripAnnotations;
7071
}
7172

@@ -170,6 +171,11 @@ public boolean isStubOnly() {
170171

171172
@Override
172173
public boolean isLenient() {
173-
return lenient;
174+
return strictness == Strictness.LENIENT;
175+
}
176+
177+
@Override
178+
public Strictness getStrictness() {
179+
return strictness;
174180
}
175181
}

src/main/java/org/mockito/internal/exceptions/Reporter.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -964,6 +964,10 @@ public static MockitoException defaultAnswerDoesNotAcceptNullParameter() {
964964
return new MockitoException("defaultAnswer() does not accept null parameter");
965965
}
966966

967+
public static MockitoException strictnessDoesNotAcceptNullParameter() {
968+
return new MockitoException("strictness() does not accept null parameter");
969+
}
970+
967971
public static MockitoException serializableWontWorkForObjectsThatDontImplementSerializable(
968972
Class<?> classToMock) {
969973
return new MockitoException(

src/main/java/org/mockito/internal/stubbing/InvocationContainerImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public class InvocationContainerImpl implements InvocationContainer, Serializabl
3838

3939
public InvocationContainerImpl(MockCreationSettings mockSettings) {
4040
this.registeredInvocations = createRegisteredInvocations(mockSettings);
41-
this.mockStrictness = mockSettings.isLenient() ? Strictness.LENIENT : null;
41+
this.mockStrictness = mockSettings.getStrictness();
4242
this.doAnswerStyleStubbing = new DoAnswerStyleStubbing();
4343
}
4444

src/main/java/org/mockito/internal/stubbing/StrictnessSelector.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ public static Strictness determineStrictness(
3131
return stubbing.getStrictness();
3232
}
3333

34-
if (mockSettings.isLenient()) {
35-
return Strictness.LENIENT;
34+
if (mockSettings.getStrictness() != null) {
35+
return mockSettings.getStrictness();
3636
}
3737

3838
return testLevelStrictness;

src/main/java/org/mockito/mock/MockCreationSettings.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,10 +118,21 @@ public interface MockCreationSettings<T> {
118118
Object getOuterClassInstance();
119119

120120
/**
121+
* @deprecated Use {@link MockCreationSettings#getStrictness()} instead.
122+
*
121123
* Informs if the mock was created with "lenient" strictness, e.g. having {@link Strictness#LENIENT} characteristic.
122124
* For more information about using mocks with lenient strictness, see {@link MockSettings#lenient()}.
123125
*
124126
* @since 2.20.0
125127
*/
128+
@Deprecated
126129
boolean isLenient();
130+
131+
/**
132+
* Sets strictness level for the mock, e.g. having {@link Strictness#STRICT_STUBS} characteristic.
133+
* For more information about using mocks with custom strictness, see {@link MockSettings#strictness(Strictness)}.
134+
*
135+
* @since 4.6.0
136+
*/
137+
Strictness getStrictness();
127138
}

0 commit comments

Comments
 (0)
0