1
- package org .springframework .beans .factory .support ;
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
+ */
2
16
3
- import static org .assertj .core .api .Assertions .assertThatThrownBy ;
4
- import static org .assertj .core .api .AssertionsForClassTypes .assertThat ;
17
+ package org .springframework .beans .factory .support ;
5
18
6
19
import java .lang .reflect .Method ;
7
20
import java .util .Map ;
21
+ import java .util .regex .Pattern ;
8
22
import java .util .stream .Stream ;
9
23
10
- import org .assertj .core .api .ThrowableAssert ;
24
+ import org .assertj .core .api .ThrowableAssert . ThrowingCallable ;
11
25
import org .junit .jupiter .api .Test ;
26
+
12
27
import org .springframework .lang .Nullable ;
13
28
29
+ import static org .assertj .core .api .Assertions .assertThatIllegalStateException ;
30
+ import static org .assertj .core .api .AssertionsForClassTypes .assertThat ;
31
+
32
+ /**
33
+ * Tests for {@link CglibSubclassingInstantiationStrategy}.
34
+ *
35
+ * @author Mikaël Francoeur
36
+ * @author Sam Brannen
37
+ * @since 6.2
38
+ */
14
39
class CglibSubclassingInstantiationStrategyTests {
15
40
16
41
private final CglibSubclassingInstantiationStrategy strategy = new CglibSubclassingInstantiationStrategy ();
17
42
18
- @ Nullable
19
- public static Object valueToReturnFromReplacer ;
20
43
21
44
@ Test
22
- void methodOverride () {
45
+ void replaceOverrideMethodInterceptorRejectsNullReturnValueForPrimitives () {
46
+ MyReplacer replacer = new MyReplacer ();
23
47
StaticListableBeanFactory beanFactory = new StaticListableBeanFactory (Map .of (
24
48
"myBean" , new MyBean (),
25
- "replacer" , new MyReplacer ()
49
+ "replacer" , replacer
26
50
));
27
51
28
- RootBeanDefinition bd = new RootBeanDefinition (MyBean .class );
29
52
MethodOverrides methodOverrides = new MethodOverrides ();
30
- Stream .of ("getBoolean" , "getShort" , "getInt" , "getLong" , "getFloat" , "getDouble" , "getByte" )
31
- .forEach (methodToOverride -> addOverride (methodOverrides , methodToOverride ));
53
+ Stream .of ("getBoolean" , "getChar" , "getByte" , "getShort" , "getInt" , "getLong" , "getFloat" , "getDouble" )
54
+ .map (methodToOverride -> new ReplaceOverride (methodToOverride , "replacer" ))
55
+ .forEach (methodOverrides ::addOverride );
56
+
57
+ RootBeanDefinition bd = new RootBeanDefinition (MyBean .class );
32
58
bd .setMethodOverrides (methodOverrides );
33
59
34
60
MyBean bean = (MyBean ) strategy .instantiate (bd , "myBean" , beanFactory );
35
61
36
- valueToReturnFromReplacer = null ;
62
+ replacer . reset () ;
37
63
assertCorrectExceptionThrownBy (bean ::getBoolean );
38
- valueToReturnFromReplacer = true ;
64
+ replacer . returnValue = true ;
39
65
assertThat (bean .getBoolean ()).isTrue ();
40
66
41
- valueToReturnFromReplacer = null ;
67
+ replacer .reset ();
68
+ assertCorrectExceptionThrownBy (bean ::getChar );
69
+ replacer .returnValue = 'x' ;
70
+ assertThat (bean .getChar ()).isEqualTo ('x' );
71
+
72
+ replacer .reset ();
73
+ assertCorrectExceptionThrownBy (bean ::getByte );
74
+ replacer .returnValue = 123 ;
75
+ assertThat (bean .getByte ()).isEqualTo ((byte ) 123 );
76
+
77
+ replacer .reset ();
42
78
assertCorrectExceptionThrownBy (bean ::getShort );
43
- valueToReturnFromReplacer = 123 ;
79
+ replacer . returnValue = 123 ;
44
80
assertThat (bean .getShort ()).isEqualTo ((short ) 123 );
45
81
46
- valueToReturnFromReplacer = null ;
82
+ replacer . reset () ;
47
83
assertCorrectExceptionThrownBy (bean ::getInt );
48
- valueToReturnFromReplacer = 123 ;
84
+ replacer . returnValue = 123 ;
49
85
assertThat (bean .getInt ()).isEqualTo (123 );
50
86
51
- valueToReturnFromReplacer = null ;
87
+ replacer . reset () ;
52
88
assertCorrectExceptionThrownBy (bean ::getLong );
53
- valueToReturnFromReplacer = 123 ;
89
+ replacer . returnValue = 123 ;
54
90
assertThat (bean .getLong ()).isEqualTo (123L );
55
91
56
- valueToReturnFromReplacer = null ;
92
+ replacer . reset () ;
57
93
assertCorrectExceptionThrownBy (bean ::getFloat );
58
- valueToReturnFromReplacer = 123 ;
94
+ replacer . returnValue = 123 ;
59
95
assertThat (bean .getFloat ()).isEqualTo (123f );
60
96
61
- valueToReturnFromReplacer = null ;
97
+ replacer . reset () ;
62
98
assertCorrectExceptionThrownBy (bean ::getDouble );
63
- valueToReturnFromReplacer = 123 ;
99
+ replacer . returnValue = 123 ;
64
100
assertThat (bean .getDouble ()).isEqualTo (123d );
65
-
66
- valueToReturnFromReplacer = null ;
67
- assertCorrectExceptionThrownBy (bean ::getByte );
68
- valueToReturnFromReplacer = 123 ;
69
- assertThat (bean .getByte ()).isEqualTo ((byte ) 123 );
70
101
}
71
102
72
- private void assertCorrectExceptionThrownBy (ThrowableAssert .ThrowingCallable runnable ) {
73
- assertThatThrownBy (runnable )
74
- .isInstanceOf (NullPointerException .class )
75
- .hasMessageMatching ("Null return value from replacer does not match primitive return type for: "
76
- + "\\ w+ org\\ .springframework\\ .beans\\ .factory\\ .support\\ .CglibSubclassingInstantiationStrategyTests\\ $MyBean\\ .\\ w+\\ (\\ )" );
77
- }
78
103
79
- private void addOverride (MethodOverrides methodOverrides , String methodToOverride ) {
80
- methodOverrides .addOverride (new ReplaceOverride (methodToOverride , "replacer" ));
104
+ private static void assertCorrectExceptionThrownBy (ThrowingCallable runnable ) {
105
+ assertThatIllegalStateException ()
106
+ .isThrownBy (runnable )
107
+ .withMessageMatching (
108
+ "Null return value from MethodReplacer does not match primitive return type for: " +
109
+ "\\ w+ %s\\ .\\ w+\\ (\\ )" .formatted (Pattern .quote (MyBean .class .getName ())));
81
110
}
82
111
112
+
83
113
static class MyBean {
114
+
84
115
boolean getBoolean () {
85
116
return true ;
86
117
}
87
118
119
+ char getChar () {
120
+ return 'x' ;
121
+ }
122
+
123
+ byte getByte () {
124
+ return 123 ;
125
+ }
126
+
88
127
short getShort () {
89
128
return 123 ;
90
129
}
@@ -104,17 +143,21 @@ float getFloat() {
104
143
double getDouble () {
105
144
return 123 ;
106
145
}
107
-
108
- byte getByte () {
109
- return 123 ;
110
- }
111
146
}
112
147
113
148
static class MyReplacer implements MethodReplacer {
114
149
150
+ @ Nullable
151
+ Object returnValue ;
152
+
153
+ void reset () {
154
+ this .returnValue = null ;
155
+ }
156
+
115
157
@ Override
116
158
public Object reimplement (Object obj , Method method , Object [] args ) {
117
- return CglibSubclassingInstantiationStrategyTests . valueToReturnFromReplacer ;
159
+ return this . returnValue ;
118
160
}
119
161
}
162
+
120
163
}
0 commit comments