У меня проблема с тестированием конечной точки контроллера покоя.Я пытаюсь отправить объект POST в конечную точку, которая помечена @Valid в поле @RequestBody.Поля сущностей снабжены правилами валидации и аннотациями Джексона.
Я пытаюсь проверить конечную точку POST с помощью модульных тестов.
Объект и поле с аннотациями
public class User {
//other fields
@Column(name = "PASSWORD", nullable = false)
@NotEmpty(message = "Users password must be filled.")
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
private String userPassword;
}
Контроллер
@RestController
@RequestMapping(value = "/api/users", produces = "application/hal+json")
public class UserController {
@PostMapping("")
public ResponseEntity<User> addNewUser(@Valid @RequestBody User newUser) {
User createdUser = userService.saveUserInDatabase(newUser);
return new ResponseEntity<>(createdUser, HttpStatus.OK);
}
}
Имодульный тест
@RunWith(MockitoJUnitRunner.class)
public class UserControllerTest {
//other tests
@Test
public void shouldBeAbleToAddNewUser() throws Exception {
User newUser = new User();
newUser.setUserName("userName");
newUser.setUserEmail("userName@domain.com");
newUser.setUserPassword("secret1");
newUser.setEnable(true);
User createdUser = new User(1L, "userName", "userName@domain.com", "secret1", true);
when(userService.saveUserInDatabase(any(User.class))).thenReturn(createdUser);
mockMvc.perform(post("/api/users")
.contentType(MediaTypes.HAL_JSON_UTF8)
.content(jsonUser.write(newUser).getJson()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.userName", Matchers.equalToIgnoringCase(createdUser.getUserName())))
.andExpect(jsonPath("$.userId", Matchers.is(createdUser.getUserId().intValue())))
.andExpect(jsonPath("$.userPassword").doesNotExist());
}
}
Что важно.Когда объект извлекается (GET) с помощью swagger, поле «userPassword» не сериализуется.Он работает, как и ожидалось, благодаря аннотации @JsonProperty.Когда объект POSTed с swagger также работает правильно, пароль сохраняется в базе данных, а ответ не содержит поля «userPassword».Кроме того, если какое-либо обязательное поле (помеченное @NotEmpty) отсутствует, генерируется исключение.
Тесты, которые проверяют выборку данных, работают правильно, 'userPassword' не является видимым ответом в json
andExpect(jsonPath("$.userPassword").doesNotExist())
Но когда присоединенный тест выполняется, он дает сбой с неправильным состоянием (400 вместо 200) и информация "Пароль пользователя должен быть заполнен."Пароль заполнен, но похоже, что он не передан в тело запроса.Я сделал некоторую отладку и заметил, что когда @JsonProperty добавляется в поле «userPassword», это поле устанавливается в «null».
// edit
jsonUser, используемый для публикации новых данных пользователя в формате JSON,определен таким образом
@RunWith(MockitoJUnitRunner.class)
public class UserControllerTest {
//other variables and methods
private JacksonTester<User> jsonUser;
@Before
public void setup() {
JacksonTester.initFields(this, new ObjectMapper());
mockMvc = MockMvcBuilders.standaloneSetup(userController).build();
}
}
// edit
Я нашел решение для моей проблемы. jsonUser.write , чтобы работать, сначала нужно прочитать данные из newUser (так очевидно) и включить аннотацию json.Поскольку getter заблокирован jsonproperty, он пропускается во время чтения.Вот почему тестовый пример не работает, но POST через swagger работает правильно.Чтобы решить эту проблему, я подготовил строку, содержащую данные в формате json
String userDetails = "{\"userName\":\"userName\",\"userEmail\":\"userName@domain.com\",\"userPassword\":\"secret1\",\"enable\":true}";
mockMvc.perform(post("/api/users")
.contentType(MediaTypes.HAL_JSON_UTF8)
.content(userDetails))
.andExpect(status().isOk());