Spring Controller在bean验证期间使用实际数据进行测试



我有一个控制器方法,用于创建如下用户。

@Secured({RoleNames.ADMIN})
@PostMapping(value = "/users/create")
public ResponseEntity<UserDto> createUser(@Valid @RequestBody CreateUserCommand command) {
UserDto userDto = userService.create(command);
return ResponseEntity.ok().body(userDto);
}

我需要验证CreateUserCommand(持有来自前端的表单数据(。例如,数据库中是否已经存在电子邮件。

我创建了一个验证器,如下所示:

public class UserEmailExistsValidator implements ConstraintValidator<UserEmailExists, CreateUserCommand> {
@Autowired
private UserService userService;
public UserEmailExistsValidator(UserService userService) {
this.userService = userService;
}
@Override
public boolean isValid(CreateUserCommand command, ConstraintValidatorContext constraintValidatorContext) {
UserDto userDto = userService.getByEmail(command.getEmail());
return userDto == null;
}
}

我的问题是:当我尝试为这个"users/create"端点运行控制器测试时,它会检查实际的数据库(而不是测试数据库(是否存在该用户的电子邮件。所以,若该用户电子邮件存在于数据库中,验证将失败,因此测试将失败。

编辑

这是我的控制器测试类

@RunWith(SpringRunner.class)
@ApplicationMvcTest(controllers = UserController.class)
public class UserControllerTest extends AbstractControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private UserService userService;
@MockBean
private Principal principal;
@Before
public void setup() {
when(principal.getName()).thenReturn("user");
}
@Test
public void shouldSaveUser_withValidRequestBody() throws Exception {
mockMvc = getMockMvcWithAuthorities(RoleNames.ADMIN);
mockMvc.perform(
post(RestEndPoint.BASE_URL + "/users/create")
.contentType(APPLICATION_JSON_UTF8)
.content(new JSONObject()
.put("username", "John Doe")
.put("email", "test@test.com")
.put("gender", "M")
.toString())
)
/* MockMvc.perform is failing (Returns status 400) due to validator class returns false... */
........
}
}

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@WebMvcTest
public @interface ApplicationMvcTest {
@AliasFor("controllers")
Class<?>[] value() default {};
@AliasFor("value")
Class<?>[] controllers() default {};
boolean useDefaultFilters() default true;
ComponentScan.Filter[] includeFilters() default {};
ComponentScan.Filter[] excludeFilters() default {};
@AliasFor(
annotation = AutoConfigureMockMvc.class,
attribute = "secure"
)
//            Change default to false
boolean secure() default false;
@AliasFor(
annotation = ImportAutoConfiguration.class,
attribute = "exclude"
)
Class<?>[] excludeAutoConfiguration() default {};
}

我使用的是Spring Boot 2.1.8,Mockito3.0.0。

如果你不想让它进入数据库,那么无论你在哪里与数据库交互,这个类都必须被嘲笑。因此,如果您使用的是存储库,那么您必须模拟它,并让它返回期望的值。如果是UserService,那么模拟它,当调用查找电子邮件的调用时,返回值。

when(userService.getByEmail(anyString())).thenReturn(null);

相关内容

  • 没有找到相关文章

最新更新