BAEL-1918 Spring StrictHttpFirewall and RequestRejectedException (#11265)
* BAEL-1918: Added code to for RequestRejectedException and StrictHttpFirewall tutorial * BAEL-1918: Added code to for RequestRejectedException and StrictHttpFirewall tutorial * BAEL:1918 - Modifed the code to accomodate comments from Michal * BAEL:1918 - Modifed the code to accomodate comments from Michal
This commit is contained in:
parent
102f09fc6c
commit
be966d6d62
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>spring-security-web-boot-3</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
|
@ -25,6 +25,20 @@
|
|||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,15 @@
|
|||
package com.baeldung.httpfirewall;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class HttpFirewallApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication application = new SpringApplication(HttpFirewallApplication.class);
|
||||
application.setAdditionalProfiles("httpfirewall");
|
||||
application.run(args);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package com.baeldung.httpfirewall;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.web.firewall.HttpFirewall;
|
||||
import org.springframework.security.web.firewall.HttpStatusRequestRejectedHandler;
|
||||
import org.springframework.security.web.firewall.RequestRejectedHandler;
|
||||
import org.springframework.security.web.firewall.StrictHttpFirewall;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@Configuration
|
||||
public class HttpFirewallConfiguration extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
//@formatter:off
|
||||
http
|
||||
.csrf()
|
||||
.disable()
|
||||
.authorizeRequests()
|
||||
.antMatchers("/error")
|
||||
.permitAll()
|
||||
.anyRequest()
|
||||
.authenticated()
|
||||
.and()
|
||||
.httpBasic();
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Bean
|
||||
public HttpFirewall configureFirewall() {
|
||||
StrictHttpFirewall strictHttpFirewall = new StrictHttpFirewall();
|
||||
strictHttpFirewall.setAllowedHttpMethods(Arrays.asList("GET", "POST", "DELETE", "OPTIONS")); // Allow only HTTP GET, POST, DELETE and OPTIONS methods
|
||||
return strictHttpFirewall;
|
||||
}
|
||||
|
||||
/*
|
||||
Use this bean if you are using Spring Security 5.4 and above
|
||||
*/
|
||||
@Bean
|
||||
public RequestRejectedHandler requestRejectedHandler() {
|
||||
return new HttpStatusRequestRejectedHandler(); // Default status code is 400. Can be customized
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package com.baeldung.httpfirewall.api;
|
||||
|
||||
import com.baeldung.httpfirewall.model.Response;
|
||||
import com.baeldung.httpfirewall.model.User;
|
||||
import com.baeldung.httpfirewall.service.UserServiceImpl;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/users")
|
||||
public class UserApi {
|
||||
|
||||
private final UserServiceImpl userServiceImpl;
|
||||
|
||||
public UserApi(UserServiceImpl userServiceImpl) {
|
||||
this.userServiceImpl = userServiceImpl;
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public ResponseEntity<Response> createUser(@RequestBody User user) {
|
||||
if (StringUtils.isBlank(user.getId())) {
|
||||
user.setId(UUID.randomUUID().toString());
|
||||
}
|
||||
userServiceImpl.saveUser(user);
|
||||
Response response = new Response(HttpStatus.CREATED.value(), "User created successfully", System.currentTimeMillis());
|
||||
URI location = URI.create("/users/" + user.getId());
|
||||
return ResponseEntity.created(location).body(response);
|
||||
}
|
||||
|
||||
@GetMapping("/{userId}")
|
||||
public User getUser(@PathVariable("userId") String userId) {
|
||||
return userServiceImpl.findById(userId).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "No user exists with the given Id"));
|
||||
}
|
||||
|
||||
@GetMapping()
|
||||
public List<User> getAllUsers() {
|
||||
return userServiceImpl.findAll().orElse(new ArrayList<>());
|
||||
}
|
||||
|
||||
@DeleteMapping("/{userId}")
|
||||
public ResponseEntity<Response> deleteUser(@PathVariable("userId") String userId) {
|
||||
userServiceImpl.deleteUser(userId);
|
||||
return ResponseEntity.ok(new Response(200, "The user has been deleted successfully", System.currentTimeMillis()));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
package com.baeldung.httpfirewall.dao;
|
||||
|
||||
import com.baeldung.httpfirewall.model.User;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
public class InMemoryUserDao {
|
||||
private Map<String, User> map = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Persists the user. The user is store in an In-Memory store (a HashMap)
|
||||
* The default implementation is an In-Memory persistence
|
||||
* @param user The user that should be persisted
|
||||
*/
|
||||
|
||||
public void save(User user) {
|
||||
map.put(user.getId(), user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the user from the in-memory data store.
|
||||
* The default implementation is an In-Memory persistence
|
||||
*
|
||||
* @param userId The ID of the user that has to be fetched
|
||||
* @return An optional of the requested user
|
||||
*/
|
||||
public Optional<User> findById(String userId) {
|
||||
return Optional.ofNullable(map.get(userId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all the users from the in-memory data store
|
||||
* The default implementation is an In-Memory persistence
|
||||
*/
|
||||
|
||||
public Optional<List<User>> findAll() {
|
||||
return Optional.of(new ArrayList<>(map.values()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the user from the data store
|
||||
* The default implementation is an In-Memory persistence
|
||||
* @param userId The user that has to be deleted
|
||||
*/
|
||||
|
||||
public void delete(String userId) {
|
||||
map.remove(userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the user exists
|
||||
* The default implementation is an In-Memory persistence
|
||||
* @param userId The user that has to be checked for
|
||||
*/
|
||||
|
||||
public boolean isExists(String userId) {
|
||||
return map.containsKey(userId);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package com.baeldung.httpfirewall.model;
|
||||
|
||||
public class Response {
|
||||
private int code;
|
||||
private String message;
|
||||
private long timestamp;
|
||||
|
||||
public Response() {
|
||||
}
|
||||
|
||||
public Response(int code, String message, long timestamp) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(int code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public long getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public void setTimestamp(long timestamp) {
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package com.baeldung.httpfirewall.model;
|
||||
|
||||
public class User {
|
||||
private String id;
|
||||
private String username;
|
||||
private String email;
|
||||
|
||||
public User() {
|
||||
}
|
||||
|
||||
public User(String id, String username, String email) {
|
||||
this.id = id;
|
||||
this.username = username;
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package com.baeldung.httpfirewall.service;
|
||||
|
||||
import com.baeldung.httpfirewall.dao.InMemoryUserDao;
|
||||
import com.baeldung.httpfirewall.model.User;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Service
|
||||
public class UserServiceImpl {
|
||||
|
||||
private final InMemoryUserDao inMemoryUserDao;
|
||||
|
||||
public UserServiceImpl(InMemoryUserDao inMemoryUserDao) {
|
||||
this.inMemoryUserDao = inMemoryUserDao;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a user. Checks if the user already exists and then persists the user
|
||||
* @param user The user that is to be persisted into the store
|
||||
*/
|
||||
public void saveUser(User user) {
|
||||
inMemoryUserDao.save(user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a user. Returns a user
|
||||
*
|
||||
* @param userId The user that has to be fetched form the repository
|
||||
*/
|
||||
public Optional<User> findById(String userId) {
|
||||
return inMemoryUserDao.findById(userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch all the users in the store
|
||||
* @return A list of all the users
|
||||
*/
|
||||
public Optional<List<User>> findAll() {
|
||||
return inMemoryUserDao.findAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the user with a given id
|
||||
* @param userId The identifier of the user
|
||||
*/
|
||||
public void deleteUser(String userId) {
|
||||
inMemoryUserDao.delete(userId);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
spring.security.user.name=user
|
||||
spring.security.user.password=password
|
|
@ -0,0 +1,114 @@
|
|||
package com.baeldung.httpfirewall.api;
|
||||
|
||||
import com.baeldung.httpfirewall.model.User;
|
||||
|
||||
import com.baeldung.httpfirewall.service.UserServiceImpl;
|
||||
import com.baeldung.httpfirewall.utility.UserTestUtility;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.test.context.support.WithMockUser;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
|
||||
|
||||
@SpringBootTest
|
||||
@AutoConfigureMockMvc
|
||||
@DisplayName("User API Live Tests")
|
||||
class UserApiLiveTest {
|
||||
|
||||
private final String userId = "1";
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@BeforeEach
|
||||
void setup() throws Exception {
|
||||
//@formatter:off
|
||||
mockMvc
|
||||
.perform(post("/api/v1/users")
|
||||
.content(objectMapper.writeValueAsString(UserTestUtility.createUserWithId(userId)))
|
||||
.contentType("application/json"));
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
@DisplayName("LiveTest User Creation")
|
||||
void givenCredentials_whenHttpPost_thenReturn201() throws Exception {
|
||||
// @formatter:off
|
||||
MvcResult result = mockMvc
|
||||
.perform(post("/api/v1/users")
|
||||
.content(objectMapper.writeValueAsString(UserTestUtility.createUserWithId("200")))
|
||||
.contentType("application/json"))
|
||||
.andDo(print())
|
||||
.andExpect(header().exists("Location")).andReturn();
|
||||
|
||||
assertEquals(HttpStatus.CREATED.value(), result.getResponse().getStatus());
|
||||
// @formatter:on
|
||||
mockMvc.perform(delete("/api/v1/users/" + 200).contentType("application/json"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
@DisplayName("LiveTest Get User")
|
||||
void givenCredentials_whenHttpGetById_thenReturnUser() throws Exception {
|
||||
// @formatter:off
|
||||
MvcResult result=mockMvc
|
||||
.perform(get("/api/v1/users/"+userId)
|
||||
.contentType("application/json")).andReturn();
|
||||
// @formatter:on
|
||||
assertEquals(HttpStatus.OK.value(), result.getResponse().getStatus());
|
||||
assertNotNull(result.getResponse());
|
||||
assertEquals(userId, objectMapper.readValue(result.getResponse().getContentAsString(), User.class).getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
@DisplayName("LiveTest Get All Users")
|
||||
void givenCredentials_whenHttpGet_thenReturnAllUsers() throws Exception {
|
||||
// @formatter:off
|
||||
MvcResult result=mockMvc
|
||||
.perform(get("/api/v1/users/")
|
||||
.contentType("application/json")).andReturn();
|
||||
// @formatter:on
|
||||
assertEquals(HttpStatus.OK.value(), result.getResponse().getStatus());
|
||||
assertNotNull(result.getResponse());
|
||||
assertNotNull(result.getResponse().getContentAsString());
|
||||
|
||||
List<User> users = objectMapper.readValue(result.getResponse().getContentAsString(), objectMapper.getTypeFactory().constructCollectionType(List.class, User.class));
|
||||
|
||||
assertEquals(1, users.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
@DisplayName("LiveTest Delete User")
|
||||
void givenCredentials_whenHttpDelete_thenDeleteUser() throws Exception {
|
||||
// @formatter:off
|
||||
MvcResult result=mockMvc
|
||||
.perform(delete("/api/v1/users/"+userId)
|
||||
.contentType("application/json")).andReturn();
|
||||
// @formatter:on
|
||||
assertEquals(HttpStatus.OK.value(), result.getResponse().getStatus());
|
||||
assertNotNull(result.getResponse());
|
||||
assertNotNull(result.getResponse().getContentAsString());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,161 @@
|
|||
package com.baeldung.httpfirewall.api;
|
||||
|
||||
import com.baeldung.httpfirewall.model.User;
|
||||
import com.baeldung.httpfirewall.service.UserServiceImpl;
|
||||
import com.baeldung.httpfirewall.utility.UserTestUtility;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.test.context.support.WithMockUser;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
|
||||
|
||||
@WebMvcTest
|
||||
@AutoConfigureMockMvc
|
||||
@DisplayName("User API Unit Tests")
|
||||
class UserApiUnitTest {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@MockBean
|
||||
private UserServiceImpl userService;
|
||||
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@Test
|
||||
@DisplayName("Test to Check Authentication")
|
||||
void whenNoAuthentication_thenThrow401() throws Exception {
|
||||
// @formatter:off
|
||||
MvcResult result = mockMvc
|
||||
.perform(post("/api/v1/users")
|
||||
.content(objectMapper.writeValueAsString(UserTestUtility.createUser()))
|
||||
.contentType("application/json"))
|
||||
.andReturn();
|
||||
assertEquals(HttpStatus.UNAUTHORIZED.value(), result.getResponse().getStatus());
|
||||
// @formatter:off
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
@DisplayName("Test Malicious URL")
|
||||
void givenCredentials_whenMaliciousUrl_thenThrowRequestRejectedException() throws Exception {
|
||||
// @formatter:off
|
||||
MvcResult result = mockMvc
|
||||
.perform(post("/api/v1\\users")
|
||||
.content(objectMapper.writeValueAsString(UserTestUtility.createUser()))
|
||||
.contentType("application/json"))
|
||||
.andDo(print())
|
||||
.andReturn();
|
||||
assertEquals(HttpStatus.BAD_REQUEST.value(), result.getResponse().getStatus());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
@DisplayName("Test User Create")
|
||||
void givenCredentials_whenHttpPost_thenReturn201() throws Exception {
|
||||
// @formatter:off
|
||||
doNothing().when(userService).saveUser(new User());
|
||||
|
||||
MvcResult result=mockMvc
|
||||
.perform(post("/api/v1/users")
|
||||
.content(objectMapper.writeValueAsString(UserTestUtility.createUser()))
|
||||
.contentType("application/json"))
|
||||
.andDo(print())
|
||||
.andExpect(header().exists("Location")).andReturn();
|
||||
assertEquals(HttpStatus.CREATED.value(), result.getResponse().getStatus());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
@DisplayName("Test User Create Without ID")
|
||||
void givenCredentials_whenHttpPostWithId_thenReturn201() throws Exception {
|
||||
// @formatter:off
|
||||
doNothing().when(userService).saveUser(new User());
|
||||
|
||||
MvcResult result = mockMvc
|
||||
.perform(post("/api/v1/users")
|
||||
.content(objectMapper.writeValueAsString(UserTestUtility.createUserWithoutId()))
|
||||
.contentType("application/json"))
|
||||
.andDo(print())
|
||||
.andExpect(header().exists("Location")).andReturn();
|
||||
assertEquals(HttpStatus.CREATED.value(), result.getResponse().getStatus());
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
@DisplayName("Test Get User")
|
||||
void givenCredentials_whenHttpGetWithId_thenReturnUser() throws Exception {
|
||||
String userId = "1";
|
||||
// @formatter:off
|
||||
when(userService.findById("1")).thenReturn(UserTestUtility.createUserWithId(userId));
|
||||
|
||||
MvcResult result = mockMvc
|
||||
.perform(get("/api/v1/users/"+userId)
|
||||
.accept("application/json"))
|
||||
.andDo(print())
|
||||
.andReturn();
|
||||
assertEquals(HttpStatus.OK.value(), result.getResponse().getStatus());
|
||||
assertNotNull(result.getResponse());
|
||||
assertEquals("jhondoe",objectMapper.readValue(result.getResponse().getContentAsString(), User.class).getUsername());
|
||||
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
@DisplayName("Test Get All Users")
|
||||
void givenCredentials_whenHttpGetWithoutId_thenReturnAllUsers() throws Exception {
|
||||
// @formatter:off
|
||||
when(userService.findAll()).thenReturn(UserTestUtility.createUsers());
|
||||
|
||||
MvcResult result = mockMvc
|
||||
.perform(get("/api/v1/users/")
|
||||
.accept("application/json"))
|
||||
.andDo(print())
|
||||
.andReturn();
|
||||
assertEquals(HttpStatus.OK.value(), result.getResponse().getStatus());
|
||||
assertNotNull(result.getResponse());
|
||||
assertTrue(result.getResponse().getContentAsString().contains("jane.doe"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
@DisplayName("Test Delete a User")
|
||||
void givenCredentials_whenHttpDelete_thenDeleteUser() throws Exception {
|
||||
String userId = "1";
|
||||
doNothing().when(userService).deleteUser(userId);
|
||||
// @formatter:off
|
||||
MvcResult result = mockMvc
|
||||
.perform(delete("/api/v1/users/"+userId)
|
||||
.accept("application/json"))
|
||||
.andDo(print())
|
||||
.andReturn();
|
||||
assertEquals(HttpStatus.OK.value(), result.getResponse().getStatus());
|
||||
assertNotNull(result.getResponse());
|
||||
assertTrue(result.getResponse().getContentAsString().contains("The user has been deleted successfully"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
package com.baeldung.httpfirewall.service;
|
||||
|
||||
import com.baeldung.httpfirewall.dao.InMemoryUserDao;
|
||||
|
||||
import com.baeldung.httpfirewall.model.User;
|
||||
import com.baeldung.httpfirewall.utility.UserTestUtility;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@DisplayName("UserService Unit Tests")
|
||||
class UserServiceUnitTest {
|
||||
|
||||
@InjectMocks
|
||||
private UserServiceImpl userService;
|
||||
|
||||
@Mock
|
||||
private InMemoryUserDao userDao;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
MockitoAnnotations.openMocks(this);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Check Create User")
|
||||
void whenCalledCreateUser_thenVerify() {
|
||||
User user = UserTestUtility.createUser();
|
||||
doNothing().when(userDao).save(user);
|
||||
|
||||
userService.saveUser(user);
|
||||
verify(userDao, times(1)).save(user);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
@DisplayName("Check Get User")
|
||||
void givenUserId_whenCalledFindById_thenReturnUser() {
|
||||
User user = UserTestUtility.createUserWithId("1").orElse(new User("1", "jhondoe", "jhon.doe@gmail.com"));
|
||||
|
||||
when(userDao.findById(user.getId())).thenReturn(Optional.of(user));
|
||||
|
||||
User actualUser = userService.findById("1").get();
|
||||
|
||||
assertNotNull(actualUser);
|
||||
assertEquals("jhondoe", actualUser.getUsername());
|
||||
verify(userDao, times(1)).findById(user.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Check Get All Users")
|
||||
void whenCalledFindAll_thenReturnAllUsers() {
|
||||
List<User> users = UserTestUtility.createUsers().orElse(new ArrayList<>());
|
||||
|
||||
when(userDao.findAll()).thenReturn(Optional.of(users));
|
||||
|
||||
Optional<List<User>> actualUsers = userService.findAll();
|
||||
|
||||
assertNotNull(actualUsers);
|
||||
assertEquals(2, users.size());
|
||||
verify(userDao, times(1)).findAll();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Check Delete Users")
|
||||
void givenId_whenCalledDeleteUser_thenDeleteUser() {
|
||||
User user = UserTestUtility.createUserWithId("1").orElse(new User());
|
||||
|
||||
doNothing().when(userDao).delete(user.getId());
|
||||
userService.deleteUser(user.getId());
|
||||
verify(userDao, times(1)).delete(user.getId());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package com.baeldung.httpfirewall.utility;
|
||||
|
||||
import com.baeldung.httpfirewall.model.User;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public class UserTestUtility {
|
||||
public static User createUser() {
|
||||
return new User(UUID.randomUUID().toString(),"jhondoe", "jhondoe@gmail.com");
|
||||
}
|
||||
|
||||
public static User createUserWithoutId() {
|
||||
return new User("","jhondoe", "jhondoe@gmail.com");
|
||||
}
|
||||
|
||||
public static Optional<User> createUserWithId(String id) {
|
||||
// @formatter:off
|
||||
return Optional.of(new User(id, "jhondoe", "jhon.doe@gmail.com"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
public static Optional<List<User>> createUsers() {
|
||||
// @formatter:off
|
||||
return Optional.of(Arrays.asList(
|
||||
new User(UUID.randomUUID().toString(), "jhondoe","jhon.doe@gmail.com" ),
|
||||
new User(UUID.randomUUID().toString(), "janedoe","jane.doe@gmail.com" ))
|
||||
);
|
||||
// @formatter:on
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue