Différences
Ci-dessous, les différences entre deux révisions de la page.
Prochaine révision | Révision précédente | ||
web:framework:spring:tests [2023/12/18 01:13] – créée jcheron | web:framework:spring:tests [2023/12/18 08:45] (Version actuelle) – [Autorisations] jcheron | ||
---|---|---|---|
Ligne 28: | Ligne 28: | ||
< | < | ||
< | < | ||
- | < | + | < |
< | < | ||
</ | </ | ||
</ | </ | ||
+ | </ | ||
+ | |||
+ | ===== @WebMvcTest ===== | ||
+ | Tester un composant (Controller, | ||
+ | |||
+ | ==== Controller ==== | ||
+ | <sxh java; | ||
+ | @Controller | ||
+ | public class HelloController { | ||
+ | @Autowired | ||
+ | private HelloService helloService; | ||
+ | |||
+ | @GetMapping("/ | ||
+ | public @ResponseBody String helloAction() { | ||
+ | return helloService.getMessage(); | ||
+ | } | ||
+ | |||
+ | @ModelAttribute(" | ||
+ | public String getMessage() { | ||
+ | return helloService.getMessage(); | ||
+ | } | ||
+ | |||
+ | @GetMapping("/ | ||
+ | public String helloViewAction() { | ||
+ | return " | ||
+ | } | ||
+ | |||
+ | @GetMapping("/ | ||
+ | public @ResponseBody String authHelloAction() { | ||
+ | return helloService.getAuthMessage(); | ||
+ | } | ||
+ | |||
+ | @GetMapping("/ | ||
+ | public String helloWithJSAction(@PathVariable String msg) { | ||
+ | return " | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | ==== Test ==== | ||
+ | |||
+ | Mocking : | ||
+ | * Serveur : <wrap round box> | ||
+ | * Service HelloService : <wrap round box> | ||
+ | |||
+ | |||
+ | <sxh java; | ||
+ | @WebMvcTest(HelloController.class) | ||
+ | @ContextConfiguration(classes = {WebSecurityConfig.class, | ||
+ | class HelloControllerTest { | ||
+ | |||
+ | @MockBean | ||
+ | private HelloService helloService; | ||
+ | |||
+ | @Autowired | ||
+ | private MockMvc mockMvc; | ||
+ | |||
+ | @Test | ||
+ | void helloShouldReturnBonjour() throws Exception { | ||
+ | // Given | ||
+ | when(helloService.getMessage()).thenReturn(" | ||
+ | // When | ||
+ | ResultActions results = this.mockMvc.perform(MockMvcRequestBuilders.get("/ | ||
+ | // Then | ||
+ | results.andExpect(MockMvcResultMatchers.status().isOk()) | ||
+ | .andExpect(content().string(containsString(" | ||
+ | } | ||
+ | |||
+ | @Test | ||
+ | void helloViewShouldReturnBonjour() throws Exception { | ||
+ | // Given | ||
+ | when(helloService.getMessage()).thenReturn(" | ||
+ | // When | ||
+ | ResultActions results = this.mockMvc.perform(MockMvcRequestBuilders.get("/ | ||
+ | // Then | ||
+ | results.andExpect(view().name(" | ||
+ | .andExpect(MockMvcResultMatchers.status().isOk()) | ||
+ | .andExpect(content().string(containsString(" | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ===== Tests d' | ||
+ | |||
+ | Test d' | ||
+ | |||
+ | <sxh java; | ||
+ | @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) | ||
+ | class HttpRequestTest { | ||
+ | |||
+ | @LocalServerPort | ||
+ | private int port; | ||
+ | |||
+ | @Autowired | ||
+ | private TestRestTemplate restTemplate; | ||
+ | |||
+ | @Test | ||
+ | void greetingShouldReturnDefaultMessage() throws Exception { | ||
+ | assertThat(this.restTemplate.getForObject(" | ||
+ | String.class)).contains(" | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== @SpringBootTest & @AutoConfigureMockMvc ==== | ||
+ | |||
+ | Mock du serveur web, remplacé par **MockMvc** : | ||
+ | |||
+ | <sxh java; | ||
+ | @SpringBootTest | ||
+ | @AutoConfigureMockMvc | ||
+ | @AutoConfigureTestDatabase(replace = Replace.NONE) | ||
+ | class RestUserControllerTest { | ||
+ | |||
+ | @Autowired | ||
+ | private MockMvc mockMvc; | ||
+ | |||
+ | @Autowired | ||
+ | private UserService userService; | ||
+ | |||
+ | private static User testUser; | ||
+ | |||
+ | |||
+ | @BeforeEach | ||
+ | public void setup() { | ||
+ | testUser = userService.createUser(" | ||
+ | } | ||
+ | |||
+ | @AfterEach | ||
+ | public void tearDown() { | ||
+ | userService.deleteAll(); | ||
+ | } | ||
+ | |||
+ | @Test | ||
+ | void getAllShouldReturnAllUsers() throws Exception { | ||
+ | this.mockMvc.perform(MockMvcRequestBuilders.get("/ | ||
+ | .andExpect(MockMvcResultMatchers.status().isOk()) | ||
+ | .andExpect(MockMvcResultMatchers.jsonPath(" | ||
+ | .andExpect(MockMvcResultMatchers.jsonPath(" | ||
+ | .andExpect(MockMvcResultMatchers.jsonPath(" | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | ===== Test sécurité ===== | ||
+ | |||
+ | ==== Authentification ==== | ||
+ | |||
+ | |||
+ | ==== Autorisations ==== | ||
+ | |||
+ | Mocking : | ||
+ | |||
+ | * Serveur web <wrap round box> | ||
+ | * Roles/Users <wrap round box> | ||
+ | |||
+ | <sxh java; | ||
+ | |||
+ | @SpringBootTest | ||
+ | @AutoConfigureMockMvc | ||
+ | class SecureApplicationTests { | ||
+ | |||
+ | @Autowired | ||
+ | private MockMvc mockMvc; | ||
+ | |||
+ | @Test | ||
+ | @WithMockUser(" | ||
+ | void authHelloWithAdminShouldReturnAdmin() throws Exception { | ||
+ | this.mockMvc.perform(get("/ | ||
+ | .andExpect(content().string(containsString(" | ||
+ | } | ||
+ | |||
+ | @Test | ||
+ | @WithAnonymousUser | ||
+ | void authHelloWithAnonymousUserShouldReturn401() throws Exception { | ||
+ | this.mockMvc.perform(get("/ | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | ===== Selenium tests ===== | ||
+ | Tests du comportement côté client | ||
+ | |||
+ | <sxh java; | ||
+ | @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) | ||
+ | class SeleniumDemoTest { | ||
+ | |||
+ | private WebDriver driver; | ||
+ | |||
+ | @LocalServerPort | ||
+ | int randomServerPort; | ||
+ | |||
+ | String baseUrl; | ||
+ | |||
+ | @SuppressWarnings(" | ||
+ | @BeforeEach | ||
+ | void setUp() throws Exception { | ||
+ | WebDriverManager.chromedriver().setup(); | ||
+ | ChromeOptions options = new ChromeOptions(); | ||
+ | options.addArguments(" | ||
+ | options.addArguments(" | ||
+ | options.addArguments(" | ||
+ | driver = new ChromeDriver(options); | ||
+ | baseUrl = " | ||
+ | navigateTo("/ | ||
+ | driver.manage().window().maximize(); | ||
+ | driver.manage().timeouts().implicitlyWait(120, | ||
+ | } | ||
+ | |||
+ | @AfterEach | ||
+ | void tearDown() throws Exception { | ||
+ | if (driver != null) { | ||
+ | driver.quit(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | private void navigateTo(String relativeURL) { | ||
+ | driver.navigate().to(baseUrl + relativeURL); | ||
+ | } | ||
+ | |||
+ | private void fillElement(String name, String content) { | ||
+ | WebElement elm = driver.findElement(By.name(name)); | ||
+ | elm.sendKeys(content); | ||
+ | } | ||
+ | |||
+ | private void btnClick(String cssSelector) { | ||
+ | driver.findElement(ByCssSelector.cssSelector(cssSelector)).click(); | ||
+ | } | ||
+ | |||
+ | private void assertElementContainsText(String cssSelector, | ||
+ | assertTrue(driver.findElement(ByCssSelector.cssSelector(cssSelector)).getText().contains(text)); | ||
+ | } | ||
+ | |||
+ | private void assertElementAttributeContainsText(String cssSelector, | ||
+ | String text) { | ||
+ | assertTrue(driver.findElement(ByCssSelector.cssSelector(cssSelector)).getAttribute(attribute) | ||
+ | .contains(text)); | ||
+ | } | ||
+ | |||
+ | public void waitForTextToAppear(String textToAppear, | ||
+ | WebDriverWait wait = new WebDriverWait(driver, | ||
+ | wait.until(ExpectedConditions.textToBePresentInElement(element, | ||
+ | } | ||
+ | |||
+ | public void waitForTextToAppear(String textToAppear, | ||
+ | waitForTextToAppear(textToAppear, | ||
+ | } | ||
+ | |||
+ | @Test | ||
+ | void helloRouteShouldReturnBonjour() { | ||
+ | assertTrue(driver.getCurrentUrl().contains(" | ||
+ | assertElementContainsText(" | ||
+ | } | ||
+ | |||
+ | @Test | ||
+ | void helloWithJsRouteShouldReturnLength() { | ||
+ | String msg = " | ||
+ | navigateTo("/ | ||
+ | assertTrue(driver.getCurrentUrl().contains("/ | ||
+ | assertElementAttributeContainsText("# | ||
+ | btnClick("# | ||
+ | assertElementContainsText("# | ||
+ | } | ||
+ | |||
+ | } | ||
+ | </ | ||
+ | |||
+ | ===== Couverture ===== | ||
+ | Intégration de **Jacoco** : | ||
+ | <sxh xml; | ||
+ | < | ||
+ | < | ||
+ | ... | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | </ | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
+ | </ | ||
</ | </ | ||