Browse Source
This commit changes the way the `MockitoTestExecutionListener` sets up mockito, now using the `MockitoSession` feature. Additionally, stubbing now defaults to a STRICT mode which can be overruled with a newly introduced annotation: `@MockitoBeanSettings`. Closes gh-33318pull/33341/head
5 changed files with 239 additions and 13 deletions
@ -0,0 +1,46 @@
@@ -0,0 +1,46 @@
|
||||
/* |
||||
* Copyright 2002-2024 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.test.context.bean.override.mockito; |
||||
|
||||
import java.lang.annotation.Documented; |
||||
import java.lang.annotation.ElementType; |
||||
import java.lang.annotation.Retention; |
||||
import java.lang.annotation.RetentionPolicy; |
||||
import java.lang.annotation.Target; |
||||
|
||||
import org.mockito.quality.Strictness; |
||||
|
||||
/** |
||||
* Configure a test class that uses {@link MockitoBean} or {@link MockitoSpyBean} |
||||
* to set up Mockito with an explicitly specified stubbing strictness. |
||||
* |
||||
* @author Simon Baslé |
||||
* @since 6.2 |
||||
* @see MockitoTestExecutionListener |
||||
*/ |
||||
@Target(ElementType.TYPE) |
||||
@Retention(RetentionPolicy.RUNTIME) |
||||
@Documented |
||||
public @interface MockitoBeanSettings { |
||||
|
||||
/** |
||||
* The stubbing strictness to apply for all Mockito mocks in the annotated |
||||
* class. |
||||
*/ |
||||
Strictness value(); |
||||
|
||||
} |
||||
@ -0,0 +1,44 @@
@@ -0,0 +1,44 @@
|
||||
/* |
||||
* Copyright 2002-2024 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.test.context.bean.override.mockito; |
||||
|
||||
import java.util.List; |
||||
|
||||
import org.junit.jupiter.api.Test; |
||||
import org.mockito.Mockito; |
||||
import org.mockito.quality.Strictness; |
||||
|
||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; |
||||
|
||||
/** |
||||
* Integration tests for explicitly-defined {@link MockitoBeanSettings} with |
||||
* lenient stubbing. |
||||
* |
||||
* @author Simon Baslé |
||||
* @since 6.2 |
||||
*/ |
||||
@SpringJUnitConfig(MockitoBeanForByNameLookupIntegrationTests.Config.class) |
||||
@MockitoBeanSettings(Strictness.LENIENT) |
||||
public class MockitoBeanSettingsLenientIntegrationTests { |
||||
|
||||
@Test |
||||
public void unusedStubbingNotReported() { |
||||
var list = Mockito.mock(List.class); |
||||
Mockito.when(list.get(Mockito.anyInt())).thenReturn(new Object()); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,96 @@
@@ -0,0 +1,96 @@
|
||||
/* |
||||
* Copyright 2002-2024 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.test.context.bean.override.mockito; |
||||
|
||||
import java.time.format.DateTimeFormatter; |
||||
import java.util.List; |
||||
import java.util.stream.Stream; |
||||
|
||||
import org.junit.jupiter.api.Named; |
||||
import org.junit.jupiter.api.Test; |
||||
import org.junit.jupiter.params.ParameterizedTest; |
||||
import org.junit.jupiter.params.provider.MethodSource; |
||||
import org.junit.platform.testkit.engine.EngineTestKit; |
||||
import org.junit.platform.testkit.engine.Events; |
||||
import org.mockito.Mockito; |
||||
import org.mockito.exceptions.misusing.UnnecessaryStubbingException; |
||||
import org.mockito.quality.Strictness; |
||||
|
||||
import org.springframework.test.context.bean.override.mockito.MockitoBeanForByNameLookupIntegrationTests.Config; |
||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; |
||||
|
||||
import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; |
||||
import static org.junit.platform.testkit.engine.EventConditions.event; |
||||
import static org.junit.platform.testkit.engine.EventConditions.finishedWithFailure; |
||||
import static org.junit.platform.testkit.engine.EventConditions.test; |
||||
import static org.junit.platform.testkit.engine.TestExecutionResultConditions.instanceOf; |
||||
import static org.junit.platform.testkit.engine.TestExecutionResultConditions.message; |
||||
|
||||
/** |
||||
* Integration tests ensuring unnecessary stubbings are reported in various |
||||
* cases where a strict style is chosen or assumed. |
||||
* |
||||
* @author Simon Baslé |
||||
* @since 6.2 |
||||
*/ |
||||
public final class MockitoBeanSettingsStrictIntegrationTests { |
||||
|
||||
private static Stream<Named<Class<?>>> strictCases() { |
||||
return Stream.of( |
||||
Named.of("explicit strictness", ExplicitStrictness.class), |
||||
Named.of("implicit strictness with @MockitoBean on field", ImplicitStrictnessWithMockitoBean.class) |
||||
); |
||||
} |
||||
|
||||
@ParameterizedTest |
||||
@MethodSource("strictCases") |
||||
public void unusedStubbingIsReported(Class<?> forCase) { |
||||
Events events = EngineTestKit.engine("junit-jupiter") |
||||
.selectors(selectClass(forCase)) |
||||
.execute() |
||||
.testEvents() |
||||
.assertStatistics(stats -> stats.started(1).failed(1)); |
||||
|
||||
events.assertThatEvents().haveExactly(1, |
||||
event(test("unnecessaryStub"), |
||||
finishedWithFailure( |
||||
instanceOf(UnnecessaryStubbingException.class), |
||||
message(msg -> msg.contains("Unnecessary stubbings detected."))))); |
||||
} |
||||
|
||||
abstract static class BaseCase { |
||||
@Test |
||||
void unnecessaryStub() { |
||||
var list = Mockito.mock(List.class); |
||||
Mockito.when(list.get(Mockito.anyInt())).thenReturn(new Object()); |
||||
} |
||||
} |
||||
|
||||
@SpringJUnitConfig(Config.class) |
||||
@MockitoBeanSettings(Strictness.STRICT_STUBS) |
||||
static class ExplicitStrictness extends BaseCase { |
||||
} |
||||
|
||||
@SpringJUnitConfig(Config.class) |
||||
static class ImplicitStrictnessWithMockitoBean extends BaseCase { |
||||
|
||||
@MockitoBean |
||||
@SuppressWarnings("unused") |
||||
DateTimeFormatter ignoredMock; |
||||
} |
||||
|
||||
} |
||||
Loading…
Reference in new issue