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 @@ |
|||||||
|
/* |
||||||
|
* 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 @@ |
|||||||
|
/* |
||||||
|
* 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 @@ |
|||||||
|
/* |
||||||
|
* 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