From 5341e777960379b6858b26eb28892c7b485676fc Mon Sep 17 00:00:00 2001 From: Sam Brannen Date: Sat, 7 Dec 2019 19:02:06 +0100 Subject: [PATCH] Introduce regression tests for prototype/request-scoped @ControllerAdvice See gh-24157 --- .../spr/ControllerAdviceIntegrationTests.java | 99 ++++++++++++++++--- 1 file changed, 85 insertions(+), 14 deletions(-) diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/spr/ControllerAdviceIntegrationTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/spr/ControllerAdviceIntegrationTests.java index 982e5e1364..144639e29d 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/spr/ControllerAdviceIntegrationTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/spr/ControllerAdviceIntegrationTests.java @@ -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 map = model.asMap(); + return "singleton:" + map.get("singleton") + + ";prototype:" + map.get("prototype") + + ";request-scoped:" + map.get("request-scoped") + + ";requestParam:" + map.get("requestParam"); } }