Reputation: 31
So, I have been testing a springboot MVC today, and when I run a test, I can not get the error to activate through using the test:
@Test
void post_A_User_passwords_do_notMatch() throws Exception {
User newUser = new User("TestName", "[email protected]", "NOT_THE_SAME","password123", true);
// * Building the request
RequestBuilder postAUser = MockMvcRequestBuilders.post("/users")
.contentType(MediaType.APPLICATION_JSON)
.header("authorization", "Bearer " + accessToken)
.content(objectMapper.writeValueAsString(newUser));
// * Sending the request
ResultActions posting = mockMvc.perform(postAUser);
// * Analysing the result
MvcResult mvcResult = posting
.andExpect(status().isBadRequest())
.andReturn();
}
The error never gets hit, even though I pass data through the mock post in JSON form. All I get is:
java.lang.AssertionError: Status expected:<400> but was:<200> Expected :400 Actual :200
So, I changed the actual original entity so that the instance fields had matching passwords and then not matching passwords, and hey presto the error was hit when the entity has non-matching passwords in the instance fields. So, this led me to the conclusion that when the mapping is called, a blank user entity template is passed into the service (Well one that is the same as it is set in the user model), then it runs through the business service, then the JSON data is saved into the repo after this occurs, then a response is sent in JSON that can be accessed.
Ideally, I want to be able to hit the error through the JSON Data when, such that if two passwords do not match on the incoming data then the error is activated, through the user service.
So, I have questions, regarding the test, trying to hit the error and the output:
The entity and then the relevant parts of the user controller and user service are posted below. I am just extending a CRUD repository for the user repo. I have set the spring security to permit all paths.
package bookapp.backend.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
import java.util.List;
@Entity
@Table(name = "users")
@Getter @Setter
public class User {
@Id // Change to UUID later after testing
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column
private Integer id;
@Column
@JsonProperty("userName")
private String userName;
@Column
private String email;
@Column
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY, value = "password")
private String password = "";
@Transient
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
@Column
private String passwordConfirmation = "";
@Column
private Boolean isAdmin;
// Relationships
// reviews
@OneToMany
private List<Review>reviewList;
// Not sure how the relationship between myLibrary and myReadBooks with books will work
// Leaving this as it is for now, but might have to change annotations etc
@OneToMany
private List<Book> myLibrary;
@OneToMany
private List<Book> myReadBooks;
// * Constructors Added for Testing
public User() {
}
public User(String userName, String email, String password, String passwordConfirmation, Boolean isAdmin) {
this.userName = userName;
this.email = email;
this.password = password;
this.passwordConfirmation = passwordConfirmation;
this.isAdmin = isAdmin;
}
// * ToString Added for Testing
@Override
public String toString() {
return "User{" +
"id=" + id +
", userName='" + userName + '\'' +
", email='" + email + '\'' +
", password='" + password + '\'' +
", passwordConfirmation='" + passwordConfirmation + '\'' +
", isAdmin=" + isAdmin +
'}';
}
}
This controller method in the controller
// ! Create a new user
@PostMapping("/users")
public User postUser(@RequestBody @Valid User user) { return userService.createUser(user); }
It also has this method in the service:
// ! This method creates a new user in the UserRepo
public User createUser(User user) {
// ! Check if password matches the passwordConfirmation
if (!user.getPassword().equals(user.getPasswordConfirmation())) {
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Password does not match password confirmation");
}
// ! Check if the user already exists in the UserRepo
// Optional<User> existingUser = userRepo.findByUsername(user.getUserName());
// if (existingUser.isPresent()) {
// throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "A user with that username already exists");
// }
// ! Encrypt password with bCrypt
String encodedPassword = bCryptPasswordEncoder.encode(user.getPassword());
user.setPassword(encodedPassword);
return userRepo.save(user);
}
Upvotes: 0
Views: 2150
Reputation: 31
@Test
void post_A_User_ErrorCheck2() throws Exception {
objectMapper.disable(MapperFeature.USE_ANNOTATIONS);
User newUser = new User("testName", "[email protected]", "password$DO_NOT_MATCH123","password$123", true);
// * Building the request
RequestBuilder postAnUser = MockMvcRequestBuilders
.post("/users")
.contentType(MediaType.APPLICATION_JSON)
.header("authorization", "Bearer " + accessToken)
.content(objectMapper.writeValueAsString(newUser));
// * Performing the Request
ResultActions postingAnUser = mockMvc.perform(postAnUser);
// * Analysing the results
MvcResult testResult = postingAnUser
.andExpect(status().isNotFound())
.andReturn();
}
So, it turned out that the JSON ignore property @JsonProperty(access = JsonProperty.Access.WRITE_ONLY, value = "password")
that annotates the entity prevents the serialization of the data. This occurs on the object mapper object that is present in the test. The @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
is needed to prevent the passwords from getting returned in the response, but in this case, we use objectMapper.disable(MapperFeature.USE_ANNOTATIONS)
, to allow them to be written. Furthermore, the test in the @Test
has an error isBadrequest()
that does not match the HttpStatus.NOT_FOUND
error in the user service.
Upvotes: 1