Skip to content

Commit 3b82733

Browse files
committed
Support @⁠Mockito[Spy]Bean & @⁠TestBean w/ @⁠DirtiesContext "before method" modes
Closes gh-33783
1 parent ba8024d commit 3b82733

File tree

11 files changed

+279
-17
lines changed

11 files changed

+279
-17
lines changed

framework-docs/modules/ROOT/pages/testing/testcontext-framework/tel-config.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ by default, exactly in the following order:
1010
annotation for "`before`" modes.
1111
* `ApplicationEventsTestExecutionListener`: Provides support for
1212
xref:testing/testcontext-framework/application-events.adoc[`ApplicationEvents`].
13+
* `BeanOverrideTestExecutionListener`: Provides support for xref:testing/testcontext-framework/bean-overriding.adoc[] .
1314
* `DependencyInjectionTestExecutionListener`: Provides dependency injection for the test
1415
instance.
1516
* `MicrometerObservationRegistryTestExecutionListener`: Provides support for
@@ -25,7 +26,6 @@ by default, exactly in the following order:
2526
* `EventPublishingTestExecutionListener`: Publishes test execution events to the test's
2627
`ApplicationContext` (see xref:testing/testcontext-framework/test-execution-events.adoc[Test Execution Events]).
2728
* `MockitoResetTestExecutionListener`: Resets mocks as configured by `@MockitoBean` or `@MockitoSpyBean`.
28-
* `BeanOverrideTestExecutionListener`: Provides support for xref:testing/testcontext-framework/bean-overriding.adoc[] .
2929

3030
[[testcontext-tel-config-registering-tels]]
3131
== Registering `TestExecutionListener` Implementations

spring-test/src/main/java/org/springframework/test/context/TestExecutionListener.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@
6666
* DirtiesContextBeforeModesTestExecutionListener}</li>
6767
* <li>{@link org.springframework.test.context.event.ApplicationEventsTestExecutionListener
6868
* ApplicationEventsTestExecutionListener}</li>
69+
* <li>{@link org.springframework.test.context.bean.override.BeanOverrideTestExecutionListener
70+
* BeanOverrideTestExecutionListener}</li>
6971
* <li>{@link org.springframework.test.context.support.DependencyInjectionTestExecutionListener
7072
* DependencyInjectionTestExecutionListener}</li>
7173
* <li>{@link org.springframework.test.context.observation.MicrometerObservationRegistryTestExecutionListener
@@ -82,8 +84,6 @@
8284
* EventPublishingTestExecutionListener}</li>
8385
* <li>{@link org.springframework.test.context.bean.override.mockito.MockitoResetTestExecutionListener
8486
* MockitoResetTestExecutionListener}</li>
85-
* <li>{@link org.springframework.test.context.bean.override.BeanOverrideTestExecutionListener
86-
* BeanOverrideTestExecutionListener}</li>
8787
* </ul>
8888
*
8989
* @author Sam Brannen

spring-test/src/main/java/org/springframework/test/context/TestExecutionListeners.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,14 +82,14 @@
8282
* @see org.springframework.test.context.web.ServletTestExecutionListener
8383
* @see org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener
8484
* @see org.springframework.test.context.event.ApplicationEventsTestExecutionListener
85+
* @see org.springframework.test.context.bean.override.BeanOverrideTestExecutionListener
8586
* @see org.springframework.test.context.support.DependencyInjectionTestExecutionListener
8687
* @see org.springframework.test.context.support.DirtiesContextTestExecutionListener
8788
* @see org.springframework.test.context.support.CommonCachesTestExecutionListener
8889
* @see org.springframework.test.context.transaction.TransactionalTestExecutionListener
8990
* @see org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener
9091
* @see org.springframework.test.context.event.EventPublishingTestExecutionListener
9192
* @see org.springframework.test.context.bean.override.mockito.MockitoResetTestExecutionListener
92-
* @see org.springframework.test.context.bean.override.BeanOverrideTestExecutionListener
9393
*/
9494
@AliasFor("value")
9595
Class<? extends TestExecutionListener>[] listeners() default {};

spring-test/src/main/java/org/springframework/test/context/bean/override/BeanOverrideTestExecutionListener.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,15 @@
3737
public class BeanOverrideTestExecutionListener extends AbstractTestExecutionListener {
3838

3939
/**
40-
* Executes almost last ({@code LOWEST_PRECEDENCE - 50}).
40+
* Returns {@code 1950}, which ensures that the {@code BeanOverrideTestExecutionListener}
41+
* is ordered after the
42+
* {@link org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener
43+
* DirtiesContextBeforeModesTestExecutionListener} and just before the
44+
* {@link DependencyInjectionTestExecutionListener}.
4145
*/
4246
@Override
4347
public int getOrder() {
44-
return LOWEST_PRECEDENCE - 50;
48+
return 1950;
4549
}
4650

4751
/**

spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoResetTestExecutionListener.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,16 +54,17 @@
5454
*/
5555
public class MockitoResetTestExecutionListener extends AbstractTestExecutionListener {
5656

57-
static final boolean mockitoPresent = ClassUtils.isPresent("org.mockito.Mockito",
57+
private static final boolean mockitoPresent = ClassUtils.isPresent("org.mockito.Mockito",
5858
MockitoResetTestExecutionListener.class.getClassLoader());
5959

6060
private static final String SPRING_MOCKITO_PACKAGE = "org.springframework.test.context.bean.override.mockito";
6161

6262
private static final Predicate<MergedAnnotation<?>> isSpringMockitoAnnotation = mergedAnnotation ->
6363
mergedAnnotation.getType().getPackageName().equals(SPRING_MOCKITO_PACKAGE);
6464

65+
6566
/**
66-
* Executes before {@link org.springframework.test.context.bean.override.BeanOverrideTestExecutionListener}.
67+
* Returns {@code Ordered.LOWEST_PRECEDENCE - 100}.
6768
*/
6869
@Override
6970
public int getOrder() {

spring-test/src/main/resources/META-INF/spring.factories

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ org.springframework.test.context.TestExecutionListener = \
44
org.springframework.test.context.web.ServletTestExecutionListener,\
55
org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener,\
66
org.springframework.test.context.event.ApplicationEventsTestExecutionListener,\
7+
org.springframework.test.context.bean.override.BeanOverrideTestExecutionListener,\
78
org.springframework.test.context.support.DependencyInjectionTestExecutionListener,\
89
org.springframework.test.context.observation.MicrometerObservationRegistryTestExecutionListener,\
910
org.springframework.test.context.support.DirtiesContextTestExecutionListener,\
1011
org.springframework.test.context.support.CommonCachesTestExecutionListener,\
1112
org.springframework.test.context.transaction.TransactionalTestExecutionListener,\
1213
org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener,\
1314
org.springframework.test.context.event.EventPublishingTestExecutionListener,\
14-
org.springframework.test.context.bean.override.mockito.MockitoResetTestExecutionListener,\
15-
org.springframework.test.context.bean.override.BeanOverrideTestExecutionListener
15+
org.springframework.test.context.bean.override.mockito.MockitoResetTestExecutionListener
1616

1717
# Default ContextCustomizerFactory implementations for the Spring TestContext Framework
1818
#

spring-test/src/test/java/org/springframework/test/context/TestExecutionListenersTests.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -68,15 +68,15 @@ void defaultListeners() {
6868
List<Class<?>> expected = asList(ServletTestExecutionListener.class,//
6969
DirtiesContextBeforeModesTestExecutionListener.class,//
7070
ApplicationEventsTestExecutionListener.class,//
71+
BeanOverrideTestExecutionListener.class,//
7172
DependencyInjectionTestExecutionListener.class,//
7273
micrometerListenerClass,//
7374
DirtiesContextTestExecutionListener.class,//
7475
CommonCachesTestExecutionListener.class, //
7576
TransactionalTestExecutionListener.class,//
7677
SqlScriptsTestExecutionListener.class,//
7778
EventPublishingTestExecutionListener.class,//
78-
MockitoResetTestExecutionListener.class,//
79-
BeanOverrideTestExecutionListener.class
79+
MockitoResetTestExecutionListener.class//
8080
);
8181
assertRegisteredListeners(DefaultListenersTestCase.class, expected);
8282
}
@@ -90,15 +90,15 @@ void defaultListenersMergedWithCustomListenerPrepended() {
9090
ServletTestExecutionListener.class,//
9191
DirtiesContextBeforeModesTestExecutionListener.class,//
9292
ApplicationEventsTestExecutionListener.class,//
93+
BeanOverrideTestExecutionListener.class,//
9394
DependencyInjectionTestExecutionListener.class,//
9495
micrometerListenerClass,//
9596
DirtiesContextTestExecutionListener.class,//
9697
CommonCachesTestExecutionListener.class, //
9798
TransactionalTestExecutionListener.class,//
9899
SqlScriptsTestExecutionListener.class,//
99100
EventPublishingTestExecutionListener.class,//
100-
MockitoResetTestExecutionListener.class,//
101-
BeanOverrideTestExecutionListener.class
101+
MockitoResetTestExecutionListener.class//
102102
);
103103
assertRegisteredListeners(MergedDefaultListenersWithCustomListenerPrependedTestCase.class, expected);
104104
}
@@ -111,6 +111,7 @@ void defaultListenersMergedWithCustomListenerAppended() {
111111
List<Class<?>> expected = asList(ServletTestExecutionListener.class,//
112112
DirtiesContextBeforeModesTestExecutionListener.class,//
113113
ApplicationEventsTestExecutionListener.class,//
114+
BeanOverrideTestExecutionListener.class,//
114115
DependencyInjectionTestExecutionListener.class,//
115116
micrometerListenerClass,//
116117
DirtiesContextTestExecutionListener.class,//
@@ -119,7 +120,6 @@ void defaultListenersMergedWithCustomListenerAppended() {
119120
SqlScriptsTestExecutionListener.class,//
120121
EventPublishingTestExecutionListener.class,//
121122
MockitoResetTestExecutionListener.class,//
122-
BeanOverrideTestExecutionListener.class,//
123123
BazTestExecutionListener.class
124124
);
125125
assertRegisteredListeners(MergedDefaultListenersWithCustomListenerAppendedTestCase.class, expected);
@@ -133,6 +133,7 @@ void defaultListenersMergedWithCustomListenerInserted() {
133133
List<Class<?>> expected = asList(ServletTestExecutionListener.class,//
134134
DirtiesContextBeforeModesTestExecutionListener.class,//
135135
ApplicationEventsTestExecutionListener.class,//
136+
BeanOverrideTestExecutionListener.class,//
136137
DependencyInjectionTestExecutionListener.class,//
137138
BarTestExecutionListener.class,//
138139
micrometerListenerClass,//
@@ -141,8 +142,7 @@ void defaultListenersMergedWithCustomListenerInserted() {
141142
TransactionalTestExecutionListener.class,//
142143
SqlScriptsTestExecutionListener.class,//
143144
EventPublishingTestExecutionListener.class,//
144-
MockitoResetTestExecutionListener.class,//
145-
BeanOverrideTestExecutionListener.class
145+
MockitoResetTestExecutionListener.class//
146146
);
147147
assertRegisteredListeners(MergedDefaultListenersWithCustomListenerInsertedTestCase.class, expected);
148148
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
* Copyright 2002-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.test.context.bean.override.convention;
18+
19+
import org.junit.jupiter.api.RepeatedTest;
20+
21+
import org.springframework.beans.factory.annotation.Autowired;
22+
import org.springframework.context.annotation.Configuration;
23+
import org.springframework.context.annotation.Import;
24+
import org.springframework.test.annotation.DirtiesContext;
25+
import org.springframework.test.annotation.DirtiesContext.MethodMode;
26+
import org.springframework.test.context.bean.override.example.ExampleService;
27+
import org.springframework.test.context.bean.override.example.ExampleServiceCaller;
28+
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
29+
30+
import static org.assertj.core.api.Assertions.assertThat;
31+
import static org.mockito.BDDMockito.given;
32+
import static org.mockito.Mockito.mock;
33+
import static org.springframework.test.annotation.DirtiesContext.MethodMode.BEFORE_METHOD;
34+
35+
/**
36+
* Integration tests for using {@link TestBean @TestBean} with
37+
* {@link DirtiesContext @DirtiesContext} and {@link MethodMode#BEFORE_METHOD}.
38+
*
39+
* @author Sam Brannen
40+
* @since 6.2
41+
*/
42+
@SpringJUnitConfig
43+
class TestBeanWithDirtiesContextBeforeMethodIntegrationTests {
44+
45+
@Autowired
46+
ExampleServiceCaller caller;
47+
48+
@TestBean
49+
ExampleService service;
50+
51+
@Autowired
52+
ExampleService autowiredService;
53+
54+
55+
static ExampleService service() {
56+
return mock();
57+
}
58+
59+
60+
@RepeatedTest(2)
61+
@DirtiesContext(methodMode = BEFORE_METHOD)
62+
void testOverride() {
63+
assertThat(service).isSameAs(autowiredService);
64+
65+
given(service.greeting()).willReturn("Spring");
66+
assertThat(caller.sayGreeting()).isEqualTo("I say Spring");
67+
}
68+
69+
70+
@Configuration(proxyBeanMethods = false)
71+
@Import(ExampleServiceCaller.class)
72+
static class Config {
73+
}
74+
75+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright 2002-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.test.context.bean.override.example;
18+
19+
/**
20+
* Example service implementation for spy tests.
21+
*
22+
* @author Phillip Webb
23+
* @since 6.2
24+
*/
25+
public class SimpleExampleService extends RealExampleService {
26+
27+
public SimpleExampleService() {
28+
super("simple");
29+
}
30+
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
* Copyright 2002-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.test.context.bean.override.mockito.integration;
18+
19+
import org.junit.jupiter.api.RepeatedTest;
20+
21+
import org.springframework.beans.factory.annotation.Autowired;
22+
import org.springframework.context.annotation.Configuration;
23+
import org.springframework.context.annotation.Import;
24+
import org.springframework.test.annotation.DirtiesContext;
25+
import org.springframework.test.annotation.DirtiesContext.MethodMode;
26+
import org.springframework.test.context.bean.override.example.ExampleService;
27+
import org.springframework.test.context.bean.override.example.ExampleServiceCaller;
28+
import org.springframework.test.context.bean.override.mockito.MockitoBean;
29+
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
30+
31+
import static org.assertj.core.api.Assertions.assertThat;
32+
import static org.mockito.BDDMockito.given;
33+
import static org.springframework.test.annotation.DirtiesContext.MethodMode.BEFORE_METHOD;
34+
35+
/**
36+
* Integration tests for using {@link MockitoBean @MockitoBean} with
37+
* {@link DirtiesContext @DirtiesContext} and {@link MethodMode#BEFORE_METHOD}.
38+
*
39+
* @author Andy Wilkinson
40+
* @author Sam Brannen
41+
* @since 6.2
42+
* @see MockitoSpyBeanWithDirtiesContextBeforeMethodIntegrationTests
43+
*/
44+
@SpringJUnitConfig
45+
class MockitoBeanWithDirtiesContextBeforeMethodIntegrationTests {
46+
47+
@Autowired
48+
ExampleServiceCaller caller;
49+
50+
@MockitoBean
51+
ExampleService service;
52+
53+
@Autowired
54+
ExampleService autowiredService;
55+
56+
57+
@RepeatedTest(2)
58+
@DirtiesContext(methodMode = BEFORE_METHOD)
59+
void testMocking() {
60+
assertThat(service).isSameAs(autowiredService);
61+
62+
given(service.greeting()).willReturn("Spring");
63+
assertThat(caller.sayGreeting()).isEqualTo("I say Spring");
64+
}
65+
66+
67+
@Configuration(proxyBeanMethods = false)
68+
@Import(ExampleServiceCaller.class)
69+
static class Config {
70+
}
71+
72+
}

0 commit comments

Comments
 (0)