Introduce regression tests for prototype/request-scoped @ControllerAdvice

See gh-24157
This commit is contained in:
Sam Brannen
2019-12-07 19:02:06 +01:00
parent f049a6ec16
commit 5341e77796

View File

@@ -16,6 +16,7 @@
package org.springframework.test.web.servlet.samples.spr;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.Before;
@@ -25,6 +26,7 @@ import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration;
@@ -33,6 +35,7 @@ import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.annotation.RequestScope;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@@ -64,21 +67,53 @@ public class ControllerAdviceIntegrationTests {
@Before
public void setUpMockMvc() {
this.mockMvc = webAppContextSetup(wac).build();
resetCounters();
}
@Test
public void controllerAdviceIsAppliedOnlyOnce() throws Exception {
assertEquals(0, SingletonControllerAdvice.counter.get());
assertEquals(0, RequestScopedControllerAdvice.counter.get());
this.mockMvc.perform(get("/test"))//
this.mockMvc.perform(get("/test").param("requestParam", "foo"))//
.andExpect(status().isOk())//
.andExpect(forwardedUrl("singleton:1;request-scoped:1"));
.andExpect(forwardedUrl("singleton:1;prototype:1;request-scoped:1;requestParam:foo"));
assertEquals(1, SingletonControllerAdvice.counter.get());
assertEquals(1, RequestScopedControllerAdvice.counter.get());
assertEquals(1, SingletonControllerAdvice.invocationCount.get());
assertEquals(1, PrototypeControllerAdvice.invocationCount.get());
assertEquals(1, RequestScopedControllerAdvice.invocationCount.get());
}
@Test
public void prototypeAndRequestScopedControllerAdviceBeansAreNotCached() throws Exception {
this.mockMvc.perform(get("/test").param("requestParam", "foo"))//
.andExpect(status().isOk())//
.andExpect(forwardedUrl("singleton:1;prototype:1;request-scoped:1;requestParam:foo"));
// singleton @ControllerAdvice beans should not be instantiated again.
assertEquals(0, SingletonControllerAdvice.instanceCount.get());
// prototype and request-scoped @ControllerAdvice beans should be instantiated once per request.
assertEquals(1, PrototypeControllerAdvice.instanceCount.get());
assertEquals(1, RequestScopedControllerAdvice.instanceCount.get());
this.mockMvc.perform(get("/test").param("requestParam", "bar"))//
.andExpect(status().isOk())//
.andExpect(forwardedUrl("singleton:2;prototype:2;request-scoped:2;requestParam:bar"));
// singleton @ControllerAdvice beans should not be instantiated again.
assertEquals(0, SingletonControllerAdvice.instanceCount.get());
// prototype and request-scoped @ControllerAdvice beans should be instantiated once per request.
assertEquals(2, PrototypeControllerAdvice.instanceCount.get());
assertEquals(2, RequestScopedControllerAdvice.instanceCount.get());
}
private static void resetCounters() {
SingletonControllerAdvice.invocationCount.set(0);
SingletonControllerAdvice.instanceCount.set(0);
PrototypeControllerAdvice.invocationCount.set(0);
PrototypeControllerAdvice.instanceCount.set(0);
RequestScopedControllerAdvice.invocationCount.set(0);
RequestScopedControllerAdvice.instanceCount.set(0);
}
@Configuration
@EnableWebMvc
static class Config {
@@ -93,6 +128,12 @@ public class ControllerAdviceIntegrationTests {
return new SingletonControllerAdvice();
}
@Bean
@Scope("prototype")
PrototypeControllerAdvice prototypeControllerAdvice() {
return new PrototypeControllerAdvice();
}
@Bean
@RequestScope
RequestScopedControllerAdvice requestScopedControllerAdvice() {
@@ -103,22 +144,49 @@ public class ControllerAdviceIntegrationTests {
@ControllerAdvice
static class SingletonControllerAdvice {
static final AtomicInteger counter = new AtomicInteger();
static final AtomicInteger instanceCount = new AtomicInteger();
static final AtomicInteger invocationCount = new AtomicInteger();
{
instanceCount.incrementAndGet();
}
@ModelAttribute
void initModel(Model model) {
model.addAttribute("singleton", counter.incrementAndGet());
model.addAttribute("singleton", invocationCount.incrementAndGet());
}
}
@ControllerAdvice
static class PrototypeControllerAdvice {
static final AtomicInteger instanceCount = new AtomicInteger();
static final AtomicInteger invocationCount = new AtomicInteger();
{
instanceCount.incrementAndGet();
}
@ModelAttribute
void initModel(Model model) {
model.addAttribute("prototype", invocationCount.incrementAndGet());
}
}
@ControllerAdvice
static class RequestScopedControllerAdvice {
static final AtomicInteger counter = new AtomicInteger();
static final AtomicInteger instanceCount = new AtomicInteger();
static final AtomicInteger invocationCount = new AtomicInteger();
{
instanceCount.incrementAndGet();
}
@ModelAttribute
void initModel(Model model) {
model.addAttribute("request-scoped", counter.incrementAndGet());
void initModel(@RequestParam String requestParam, Model model) {
model.addAttribute("requestParam", requestParam);
model.addAttribute("request-scoped", invocationCount.incrementAndGet());
}
}
@@ -127,8 +195,11 @@ public class ControllerAdviceIntegrationTests {
@GetMapping("/test")
String get(Model model) {
return "singleton:" + model.asMap().get("singleton") + ";request-scoped:"
+ model.asMap().get("request-scoped");
Map<String, Object> map = model.asMap();
return "singleton:" + map.get("singleton") +
";prototype:" + map.get("prototype") +
";request-scoped:" + map.get("request-scoped") +
";requestParam:" + map.get("requestParam");
}
}