Skip to content

Commit 5341e77

Browse files
committed
Introduce regression tests for prototype/request-scoped @ControllerAdvice
See gh-24157
1 parent f049a6e commit 5341e77

File tree

1 file changed

+84
-13
lines changed

1 file changed

+84
-13
lines changed

spring-test/src/test/java/org/springframework/test/web/servlet/samples/spr/ControllerAdviceIntegrationTests.java

Lines changed: 84 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.test.web.servlet.samples.spr;
1818

19+
import java.util.Map;
1920
import java.util.concurrent.atomic.AtomicInteger;
2021

2122
import org.junit.Before;
@@ -25,6 +26,7 @@
2526
import org.springframework.beans.factory.annotation.Autowired;
2627
import org.springframework.context.annotation.Bean;
2728
import org.springframework.context.annotation.Configuration;
29+
import org.springframework.context.annotation.Scope;
2830
import org.springframework.stereotype.Controller;
2931
import org.springframework.test.context.junit4.SpringRunner;
3032
import org.springframework.test.context.web.WebAppConfiguration;
@@ -33,6 +35,7 @@
3335
import org.springframework.web.bind.annotation.ControllerAdvice;
3436
import org.springframework.web.bind.annotation.GetMapping;
3537
import org.springframework.web.bind.annotation.ModelAttribute;
38+
import org.springframework.web.bind.annotation.RequestParam;
3639
import org.springframework.web.context.WebApplicationContext;
3740
import org.springframework.web.context.annotation.RequestScope;
3841
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@@ -64,21 +67,53 @@ public class ControllerAdviceIntegrationTests {
6467
@Before
6568
public void setUpMockMvc() {
6669
this.mockMvc = webAppContextSetup(wac).build();
70+
resetCounters();
6771
}
6872

6973
@Test
7074
public void controllerAdviceIsAppliedOnlyOnce() throws Exception {
71-
assertEquals(0, SingletonControllerAdvice.counter.get());
72-
assertEquals(0, RequestScopedControllerAdvice.counter.get());
75+
this.mockMvc.perform(get("/test").param("requestParam", "foo"))//
76+
.andExpect(status().isOk())//
77+
.andExpect(forwardedUrl("singleton:1;prototype:1;request-scoped:1;requestParam:foo"));
78+
79+
assertEquals(1, SingletonControllerAdvice.invocationCount.get());
80+
assertEquals(1, PrototypeControllerAdvice.invocationCount.get());
81+
assertEquals(1, RequestScopedControllerAdvice.invocationCount.get());
82+
}
83+
84+
@Test
85+
public void prototypeAndRequestScopedControllerAdviceBeansAreNotCached() throws Exception {
86+
this.mockMvc.perform(get("/test").param("requestParam", "foo"))//
87+
.andExpect(status().isOk())//
88+
.andExpect(forwardedUrl("singleton:1;prototype:1;request-scoped:1;requestParam:foo"));
89+
90+
// singleton @ControllerAdvice beans should not be instantiated again.
91+
assertEquals(0, SingletonControllerAdvice.instanceCount.get());
92+
// prototype and request-scoped @ControllerAdvice beans should be instantiated once per request.
93+
assertEquals(1, PrototypeControllerAdvice.instanceCount.get());
94+
assertEquals(1, RequestScopedControllerAdvice.instanceCount.get());
7395

74-
this.mockMvc.perform(get("/test"))//
96+
this.mockMvc.perform(get("/test").param("requestParam", "bar"))//
7597
.andExpect(status().isOk())//
76-
.andExpect(forwardedUrl("singleton:1;request-scoped:1"));
98+
.andExpect(forwardedUrl("singleton:2;prototype:2;request-scoped:2;requestParam:bar"));
7799

78-
assertEquals(1, SingletonControllerAdvice.counter.get());
79-
assertEquals(1, RequestScopedControllerAdvice.counter.get());
100+
// singleton @ControllerAdvice beans should not be instantiated again.
101+
assertEquals(0, SingletonControllerAdvice.instanceCount.get());
102+
// prototype and request-scoped @ControllerAdvice beans should be instantiated once per request.
103+
assertEquals(2, PrototypeControllerAdvice.instanceCount.get());
104+
assertEquals(2, RequestScopedControllerAdvice.instanceCount.get());
80105
}
81106

107+
private static void resetCounters() {
108+
SingletonControllerAdvice.invocationCount.set(0);
109+
SingletonControllerAdvice.instanceCount.set(0);
110+
PrototypeControllerAdvice.invocationCount.set(0);
111+
PrototypeControllerAdvice.instanceCount.set(0);
112+
RequestScopedControllerAdvice.invocationCount.set(0);
113+
RequestScopedControllerAdvice.instanceCount.set(0);
114+
}
115+
116+
82117
@Configuration
83118
@EnableWebMvc
84119
static class Config {
@@ -93,6 +128,12 @@ SingletonControllerAdvice singletonControllerAdvice() {
93128
return new SingletonControllerAdvice();
94129
}
95130

131+
@Bean
132+
@Scope("prototype")
133+
PrototypeControllerAdvice prototypeControllerAdvice() {
134+
return new PrototypeControllerAdvice();
135+
}
136+
96137
@Bean
97138
@RequestScope
98139
RequestScopedControllerAdvice requestScopedControllerAdvice() {
@@ -103,22 +144,49 @@ RequestScopedControllerAdvice requestScopedControllerAdvice() {
103144
@ControllerAdvice
104145
static class SingletonControllerAdvice {
105146

106-
static final AtomicInteger counter = new AtomicInteger();
147+
static final AtomicInteger instanceCount = new AtomicInteger();
148+
static final AtomicInteger invocationCount = new AtomicInteger();
149+
150+
{
151+
instanceCount.incrementAndGet();
152+
}
107153

108154
@ModelAttribute
109155
void initModel(Model model) {
110-
model.addAttribute("singleton", counter.incrementAndGet());
156+
model.addAttribute("singleton", invocationCount.incrementAndGet());
111157
}
112158
}
113159

114160
@ControllerAdvice
115-
static class RequestScopedControllerAdvice {
161+
static class PrototypeControllerAdvice {
116162

117-
static final AtomicInteger counter = new AtomicInteger();
163+
static final AtomicInteger instanceCount = new AtomicInteger();
164+
static final AtomicInteger invocationCount = new AtomicInteger();
165+
166+
{
167+
instanceCount.incrementAndGet();
168+
}
118169

119170
@ModelAttribute
120171
void initModel(Model model) {
121-
model.addAttribute("request-scoped", counter.incrementAndGet());
172+
model.addAttribute("prototype", invocationCount.incrementAndGet());
173+
}
174+
}
175+
176+
@ControllerAdvice
177+
static class RequestScopedControllerAdvice {
178+
179+
static final AtomicInteger instanceCount = new AtomicInteger();
180+
static final AtomicInteger invocationCount = new AtomicInteger();
181+
182+
{
183+
instanceCount.incrementAndGet();
184+
}
185+
186+
@ModelAttribute
187+
void initModel(@RequestParam String requestParam, Model model) {
188+
model.addAttribute("requestParam", requestParam);
189+
model.addAttribute("request-scoped", invocationCount.incrementAndGet());
122190
}
123191
}
124192

@@ -127,8 +195,11 @@ static class TestController {
127195

128196
@GetMapping("/test")
129197
String get(Model model) {
130-
return "singleton:" + model.asMap().get("singleton") + ";request-scoped:"
131-
+ model.asMap().get("request-scoped");
198+
Map<String, Object> map = model.asMap();
199+
return "singleton:" + map.get("singleton") +
200+
";prototype:" + map.get("prototype") +
201+
";request-scoped:" + map.get("request-scoped") +
202+
";requestParam:" + map.get("requestParam");
132203
}
133204
}
134205

0 commit comments

Comments
 (0)