如何使用 H2 数据库中的用户预加载 Spring 引导集成测试?
How do I pre-load my Spring Boot integration test with a user from my H2 database?
我正在使用 Spring Boot 2.1。我还在内存数据库中使用 H2。我在 src/test/resources/data.sql:
创建了这个文件
insert into roles (id, name) values ('1be4965cb4f311eaa2b76a0000c30600', 'USER');
insert into roles (id, name) values ('1be6b2acb4f311eaa2b76a0000c30600', 'ADMIN');
insert into privileges (id, name) values ('1be4965cb4f311eaa2b76a0000c30600', 'USER');
insert into privileges (id, name) values ('1be6b2acb4f311eaa2b76a0000c30600', 'SUPER_ADMIN');
insert into roles_privileges (role_id, privilege_id) VALUES ('1be4965cb4f311eaa2b76a0000c30600', '1be4965cb4f311eaa2b76a0000c30600');
insert into roles_privileges (role_id, privilege_id) VALUES ('1be6b2acb4f311eaa2b76a0000c30600', '1be6b2acb4f311eaa2b76a0000c30600');
insert into occasions (id, name) values ('97c625b8b63511ea9d386a0000c30600', 'Birthday');
insert into users (id, email, enabled, first_name, last_name, password, token_expired) values ('aa7625b8b63512929d386a0000c30600', 'me@example.com', true, 'lone', 'ranger', 'password', false);
insert into users_roles (user_id, role_id) values ('aa7625b8b63512929d386a0000c30600', '1be6b2acb4f311eaa2b76a0000c30600');
我想创建一个 spring 引导集成测试来测试以下方法...
@RestController
@RequestMapping("/api/cards")
public class CardController {
@Autowired
private CardService cardService;
@PostMapping
@ResponseStatus(code = HttpStatus.CREATED)
public void create(@RequestBody Card card, @AuthenticationPrincipal User loggedInUser) {
card.setAuthor(loggedInUser);
cardService.save(card);
}
我想在我的数据库中加载一个用户,但我不太确定最简单的方法。我尝试了“@WithMockUser”,但没有加载此用户...
@SpringBootTest(classes = CardmaniaApplication.class,
webEnvironment = WebEnvironment.RANDOM_PORT)
public class CardControllerIntegrationTest {
@LocalServerPort
private int port;
@Autowired
private TestRestTemplate restTemplate;
@Autowired
private ICardRepository cardRepository;
@Autowired
private IUserRepository userRepository;
@Autowired
private IOccasionRepository occasionRepository;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Value("${jwt.http.request.header}")
private String tokenHeader;
@BeforeEach
void setup() {
UserDetails user = (UserDetails) userRepository.findAll().get(0);
final String token = jwtTokenUtil.generateToken(user);
restTemplate.getRestTemplate().setInterceptors(
Collections.singletonList((request, body, execution) -> {
request.getHeaders()
.add(this.tokenHeader, "Bearer " + token);
return execution.execute(request, body);
}));
}
@Test
@WithMockUser(authorities = {"ADMIN"})
void createCard() throws Exception {
final Card card = new Card();
final User author = userRepository.findAll().get(0);
card.setAuthor(author);
final Occasion occasion = occasionRepository.findAll().get(0);
card.setOccasion(occasion);
byte[] image = new byte[] {1, 1, 1, 1};
card.setImage(image);
ResponseEntity<String> responseEntity = this.restTemplate
.postForEntity("http://localhost:" + port + "/api/cards", card, String.class);
assertEquals(201, responseEntity.getStatusCodeValue());
List<Card> cards = cardRepository.findByOccasion(occasion);
assertThat(cards.size()).isEqualTo(1);
final Card cardEntity = cards.get(0);
assertThat(cardEntity.getImage()).isEqualTo(image);
}
}
我对 spring 引导还很陌生,因此不熟悉将用户预加载到我的安全主体中的最简单方法。
此设置当前存在冲突。一方面,您使用 @WithMockUser
为 SecurityContext
提供模拟用户,另一方面,您为实际身份验证准备有效的 JWT 令牌。
@WithMockUser
通常用于测试,例如无需使用正确的身份验证信息(如 JWT 或基本身份验证)创建请求即可轻松访问受保护的端点。
因此,您应该选择当前方法之一:要么模拟用户 ,要么 生成 JWT 并访问您的端点。
您的 @WithMockUser
当前无法正常工作的原因可能与默认用户名 Spring 安全选择有关。如果您希望它与您数据库中的用户相匹配,请考虑配置它:@WithMockUser(username="YOUR_USERNAME",roles={"USER","ADMIN"})
要进一步调试您的应用程序,您可以临时添加
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
到您正在测试的端点并调试它以了解哪个用户现在实际上是 SecurityContext
的一部分。
我发现答案是使用“@WithUserDetails”注解
@Test
@WithUserDetails("me@example.com")
void registrationWorksThroughAllLayers() throws Exception {
这将使用您实现 UserDetailsService 的自动装配 class 并在上面的代码中使用注释值“me@example.com”调用其 loadUserByUsername。
我正在使用 Spring Boot 2.1。我还在内存数据库中使用 H2。我在 src/test/resources/data.sql:
创建了这个文件insert into roles (id, name) values ('1be4965cb4f311eaa2b76a0000c30600', 'USER');
insert into roles (id, name) values ('1be6b2acb4f311eaa2b76a0000c30600', 'ADMIN');
insert into privileges (id, name) values ('1be4965cb4f311eaa2b76a0000c30600', 'USER');
insert into privileges (id, name) values ('1be6b2acb4f311eaa2b76a0000c30600', 'SUPER_ADMIN');
insert into roles_privileges (role_id, privilege_id) VALUES ('1be4965cb4f311eaa2b76a0000c30600', '1be4965cb4f311eaa2b76a0000c30600');
insert into roles_privileges (role_id, privilege_id) VALUES ('1be6b2acb4f311eaa2b76a0000c30600', '1be6b2acb4f311eaa2b76a0000c30600');
insert into occasions (id, name) values ('97c625b8b63511ea9d386a0000c30600', 'Birthday');
insert into users (id, email, enabled, first_name, last_name, password, token_expired) values ('aa7625b8b63512929d386a0000c30600', 'me@example.com', true, 'lone', 'ranger', 'password', false);
insert into users_roles (user_id, role_id) values ('aa7625b8b63512929d386a0000c30600', '1be6b2acb4f311eaa2b76a0000c30600');
我想创建一个 spring 引导集成测试来测试以下方法...
@RestController
@RequestMapping("/api/cards")
public class CardController {
@Autowired
private CardService cardService;
@PostMapping
@ResponseStatus(code = HttpStatus.CREATED)
public void create(@RequestBody Card card, @AuthenticationPrincipal User loggedInUser) {
card.setAuthor(loggedInUser);
cardService.save(card);
}
我想在我的数据库中加载一个用户,但我不太确定最简单的方法。我尝试了“@WithMockUser”,但没有加载此用户...
@SpringBootTest(classes = CardmaniaApplication.class,
webEnvironment = WebEnvironment.RANDOM_PORT)
public class CardControllerIntegrationTest {
@LocalServerPort
private int port;
@Autowired
private TestRestTemplate restTemplate;
@Autowired
private ICardRepository cardRepository;
@Autowired
private IUserRepository userRepository;
@Autowired
private IOccasionRepository occasionRepository;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Value("${jwt.http.request.header}")
private String tokenHeader;
@BeforeEach
void setup() {
UserDetails user = (UserDetails) userRepository.findAll().get(0);
final String token = jwtTokenUtil.generateToken(user);
restTemplate.getRestTemplate().setInterceptors(
Collections.singletonList((request, body, execution) -> {
request.getHeaders()
.add(this.tokenHeader, "Bearer " + token);
return execution.execute(request, body);
}));
}
@Test
@WithMockUser(authorities = {"ADMIN"})
void createCard() throws Exception {
final Card card = new Card();
final User author = userRepository.findAll().get(0);
card.setAuthor(author);
final Occasion occasion = occasionRepository.findAll().get(0);
card.setOccasion(occasion);
byte[] image = new byte[] {1, 1, 1, 1};
card.setImage(image);
ResponseEntity<String> responseEntity = this.restTemplate
.postForEntity("http://localhost:" + port + "/api/cards", card, String.class);
assertEquals(201, responseEntity.getStatusCodeValue());
List<Card> cards = cardRepository.findByOccasion(occasion);
assertThat(cards.size()).isEqualTo(1);
final Card cardEntity = cards.get(0);
assertThat(cardEntity.getImage()).isEqualTo(image);
}
}
我对 spring 引导还很陌生,因此不熟悉将用户预加载到我的安全主体中的最简单方法。
此设置当前存在冲突。一方面,您使用 @WithMockUser
为 SecurityContext
提供模拟用户,另一方面,您为实际身份验证准备有效的 JWT 令牌。
@WithMockUser
通常用于测试,例如无需使用正确的身份验证信息(如 JWT 或基本身份验证)创建请求即可轻松访问受保护的端点。
因此,您应该选择当前方法之一:要么模拟用户 ,要么 生成 JWT 并访问您的端点。
您的 @WithMockUser
当前无法正常工作的原因可能与默认用户名 Spring 安全选择有关。如果您希望它与您数据库中的用户相匹配,请考虑配置它:@WithMockUser(username="YOUR_USERNAME",roles={"USER","ADMIN"})
要进一步调试您的应用程序,您可以临时添加
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
到您正在测试的端点并调试它以了解哪个用户现在实际上是 SecurityContext
的一部分。
我发现答案是使用“@WithUserDetails”注解
@Test
@WithUserDetails("me@example.com")
void registrationWorksThroughAllLayers() throws Exception {
这将使用您实现 UserDetailsService 的自动装配 class 并在上面的代码中使用注释值“me@example.com”调用其 loadUserByUsername。