Skip to content

Commit 14c476b

Browse files
committed
Verify @⁠MockitoBean can replace Spring AOP advised beans
See gh-33742
1 parent a8b36f7 commit 14c476b

File tree

1 file changed

+110
-0
lines changed

1 file changed

+110
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/*
2+
* Copyright 2012-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;
18+
19+
import org.junit.jupiter.api.RepeatedTest;
20+
import org.junit.jupiter.api.extension.ExtendWith;
21+
import org.mockito.Mockito;
22+
23+
import org.springframework.aop.support.AopUtils;
24+
import org.springframework.cache.CacheManager;
25+
import org.springframework.cache.annotation.Cacheable;
26+
import org.springframework.cache.annotation.EnableCaching;
27+
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
28+
import org.springframework.cache.interceptor.CacheResolver;
29+
import org.springframework.cache.interceptor.SimpleCacheResolver;
30+
import org.springframework.context.annotation.Bean;
31+
import org.springframework.context.annotation.Configuration;
32+
import org.springframework.context.annotation.Import;
33+
import org.springframework.test.context.junit.jupiter.SpringExtension;
34+
35+
import static org.assertj.core.api.Assertions.assertThat;
36+
import static org.mockito.ArgumentMatchers.anyBoolean;
37+
import static org.mockito.ArgumentMatchers.eq;
38+
import static org.mockito.BDDMockito.given;
39+
import static org.mockito.Mockito.times;
40+
import static org.mockito.Mockito.verify;
41+
42+
/**
43+
* Tests for {@link MockitoBean @MockitoBean} used in combination Spring AOP.
44+
*
45+
* @author Sam Brannen
46+
* @author Phillip Webb
47+
* @since 6.2
48+
* @see <a href="https://github.com/spring-projects/spring-boot/issues/5837">5837</a>
49+
*/
50+
@ExtendWith(SpringExtension.class)
51+
public class MockitoBeanAndSpringAopProxyTests {
52+
53+
@MockitoBean
54+
DateService dateService;
55+
56+
57+
/**
58+
* Since the {@code BeanOverrideBeanFactoryPostProcessor} always registers a
59+
* manual singleton for a {@code @MockitoBean} mock, the mock that ends up
60+
* in the application context should not be proxied by Spring AOP (since
61+
* BeanPostProcessors are never applied to manually registered singletons).
62+
*
63+
* <p>In other words, this test effectively verifies that the mock is a
64+
* standard Mockito mock which does <strong>not</strong> have
65+
* {@link Cacheable @Cacheable} applied to it.
66+
*/
67+
@RepeatedTest(2)
68+
void mockShouldNotBeAnAopProxy() {
69+
assertThat(AopUtils.isAopProxy(dateService)).as("is Spring AOP proxy").isFalse();
70+
assertThat(Mockito.mockingDetails(dateService).isMock()).as("is Mockito mock").isTrue();
71+
72+
given(dateService.getDate(false)).willReturn(1L);
73+
Long date1 = dateService.getDate(false);
74+
assertThat(date1).isOne();
75+
76+
given(dateService.getDate(false)).willReturn(2L);
77+
Long date2 = dateService.getDate(false);
78+
assertThat(date2).isEqualTo(2L);
79+
80+
verify(dateService, times(2)).getDate(false);
81+
verify(dateService, times(2)).getDate(eq(false));
82+
verify(dateService, times(2)).getDate(anyBoolean());
83+
}
84+
85+
86+
@Configuration(proxyBeanMethods = false)
87+
@EnableCaching(proxyTargetClass = true)
88+
@Import(DateService.class)
89+
static class Config {
90+
91+
@Bean
92+
CacheResolver cacheResolver(CacheManager cacheManager) {
93+
return new SimpleCacheResolver(cacheManager);
94+
}
95+
96+
@Bean
97+
ConcurrentMapCacheManager cacheManager() {
98+
return new ConcurrentMapCacheManager("test");
99+
}
100+
}
101+
102+
static class DateService {
103+
104+
@Cacheable("test")
105+
Long getDate(boolean argument) {
106+
return System.nanoTime();
107+
}
108+
}
109+
110+
}

0 commit comments

Comments
 (0)