Skip to content

Commit

Permalink
Add fix
Browse files Browse the repository at this point in the history
fixes: #2656
  • Loading branch information
big-andy-coates committed May 31, 2022
1 parent cc62bdd commit d0bf836
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 22 deletions.
45 changes: 40 additions & 5 deletions src/main/java/org/mockito/Mock.java
Expand Up @@ -13,7 +13,6 @@
import java.lang.annotation.Target;

import org.mockito.junit.MockitoJUnitRunner;
import org.mockito.quality.Strictness;
import org.mockito.stubbing.Answer;

/**
Expand All @@ -34,12 +33,13 @@
* @Mock(name = "database") private ArticleDatabase dbMock;
* @Mock(answer = RETURNS_MOCKS) private UserProvider userProvider;
* @Mock(extraInterfaces = {Queue.class, Observer.class}) private ArticleMonitor articleMonitor;
* @Mock(strictness = Mock.Strictness.LENIENT) private ArticleConsumer articleConsumer;
* @Mock(stubOnly = true) private Logger logger;
*
* private ArticleManager manager;
*
* @Before public void setup() {
* manager = new ArticleManager(userProvider, database, calculator, articleMonitor, logger);
* manager = new ArticleManager(userProvider, database, calculator, articleMonitor, articleConsumer, logger);
* }
* }
*
Expand Down Expand Up @@ -117,10 +117,45 @@
boolean lenient() default false;

/**
* Mock will have custom strictness, see {@link MockSettings#strictness(Strictness)}.
* Mock will have custom strictness, see {@link MockSettings#strictness(org.mockito.quality.Strictness)}.
* For examples how to use 'Mock' annotation and parameters see {@link Mock}.
*
* @since 4.6.0
* @since 4.6.1
*/
Strictness strictness() default Strictness.STRICT_STUBS;
Strictness strictness() default Strictness.NOT_SET;

enum Strictness {

/**
* Default value used to indicate the mock does not override the test level strictness.
*
* @since 4.6.1
*/
NOT_SET(null),

/**
* See {@link org.mockito.quality.Strictness#LENIENT}
*/
LENIENT(org.mockito.quality.Strictness.LENIENT),

/**
* See {@link org.mockito.quality.Strictness#WARN}
*/
WARN(org.mockito.quality.Strictness.WARN),

/**
* See {@link org.mockito.quality.Strictness#STRICT_STUBS}
*/
STRICT_STUBS(org.mockito.quality.Strictness.STRICT_STUBS);

private final org.mockito.quality.Strictness outer;

Strictness(org.mockito.quality.Strictness outer) {
this.outer = outer;
}

public org.mockito.quality.Strictness outer() {
return outer;
}
}
}
Expand Up @@ -28,6 +28,7 @@ public Object process(Mock annotation, Field field) {
annotation, field.getType(), field::getGenericType, field.getName());
}

@SuppressWarnings("deprecation")
public static Object processAnnotationForMock(
Mock annotation, Class<?> type, Supplier<Type> genericType, String name) {
MockSettings mockSettings = Mockito.withSettings();
Expand All @@ -45,10 +46,12 @@ public static Object processAnnotationForMock(
if (annotation.stubOnly()) {
mockSettings.stubOnly();
}
mockSettings.strictness(annotation.strictness());
if (annotation.lenient()) {
mockSettings.lenient();
}
if (annotation.strictness() != Mock.Strictness.NOT_SET) {
mockSettings.strictness(annotation.strictness().outer());
}

// see @Mock answer default value
mockSettings.defaultAnswer(annotation.answer());
Expand Down
Expand Up @@ -247,10 +247,10 @@ public MockSettings lenient() {

@Override
public MockSettings strictness(Strictness strictness) {
this.strictness = strictness;
if (strictness == null) {
throw strictnessDoesNotAcceptNullParameter();
}
this.strictness = strictness;
return this;
}

Expand Down
Expand Up @@ -45,7 +45,7 @@ public class CreationSettings<T> implements MockCreationSettings<T>, Serializabl
private boolean useConstructor;
private Object outerClassInstance;
private Object[] constructorArgs;
protected Strictness strictness = Strictness.STRICT_STUBS;
protected Strictness strictness = null;

public CreationSettings() {}

Expand Down
32 changes: 32 additions & 0 deletions src/test/java/org/mockito/MockTest.java
@@ -0,0 +1,32 @@
/*
* Copyright (c) 2022 Mockito contributors
* This program is made available under the terms of the MIT License.
*/
package org.mockito;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import static org.assertj.core.api.Assertions.assertThat;

@RunWith(value = Parameterized.class)
public class MockTest {

public org.mockito.quality.Strictness strictness;

public MockTest(org.mockito.quality.Strictness strictness) {
this.strictness = strictness;
}

@Test
public void should_have_matching_enum_in_mock_strictness_enum() {
final Mock.Strictness mockStrictness = Mock.Strictness.valueOf(this.strictness.name());
assertThat(mockStrictness.outer()).isEqualTo(strictness);
}

@Parameterized.Parameters
public static org.mockito.quality.Strictness[] data() {
return org.mockito.quality.Strictness.values();
}
}
Expand Up @@ -7,6 +7,8 @@
import org.assertj.core.api.Assertions;
import org.junit.Rule;
import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.exceptions.misusing.PotentialStubbingProblem;
import org.mockito.junit.MockitoJUnit;
Expand All @@ -16,28 +18,56 @@

import static org.mockito.Mockito.when;

@RunWith(Enclosed.class)
public class StrictnessMockAnnotationTest {

public @Rule MockitoRule rule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);
public static class StrictStubsTest {
public @Rule MockitoRule rule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);

@Mock(strictness = Strictness.LENIENT)
IMethods lenientMock;
@Mock(strictness = Mock.Strictness.LENIENT)
IMethods lenientMock;

@Mock IMethods regularMock;
@Mock IMethods regularMock;

@Test
public void mock_is_lenient() {
when(lenientMock.simpleMethod("1")).thenReturn("1");
@Test
public void mock_is_lenient() {
when(lenientMock.simpleMethod("1")).thenReturn("1");

// then lenient mock does not throw:
ProductionCode.simpleMethod(lenientMock, "3");
// then lenient mock does not throw:
ProductionCode.simpleMethod(lenientMock, "3");
}

@Test
public void mock_is_strict() {
when(regularMock.simpleMethod("2")).thenReturn("2");

Assertions.assertThatThrownBy(() -> ProductionCode.simpleMethod(regularMock, "4"))
.isInstanceOf(PotentialStubbingProblem.class);
}
}

@Test
public void mock_is_strict() {
when(regularMock.simpleMethod("2")).thenReturn("2");
public static class LenientStubsTest {
public @Rule MockitoRule rule = MockitoJUnit.rule().strictness(Strictness.LENIENT);

@Mock IMethods lenientMock;

@Mock(strictness = Mock.Strictness.STRICT_STUBS)
IMethods regularMock;

@Test
public void mock_is_lenient() {
when(lenientMock.simpleMethod("1")).thenReturn("1");

// then lenient mock does not throw:
ProductionCode.simpleMethod(lenientMock, "3");
}

@Test
public void mock_is_strict() {
when(regularMock.simpleMethod("2")).thenReturn("2");

Assertions.assertThatThrownBy(() -> ProductionCode.simpleMethod(regularMock, "4"))
.isInstanceOf(PotentialStubbingProblem.class);
Assertions.assertThatThrownBy(() -> ProductionCode.simpleMethod(regularMock, "4"))
.isInstanceOf(PotentialStubbingProblem.class);
}
}
}
@@ -1,3 +1,7 @@
/*
* Copyright (c) 2022 Mockito contributors
* This program is made available under the terms of the MIT License.
*/
package org.mockitousage;

import java.util.function.Predicate;
Expand Down

0 comments on commit d0bf836

Please sign in to comment.