1

我正在使用 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 boot集成测试来测试以下方法...

@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 Boot 还很陌生,因此不熟悉将用户预加载到我的安全主体中的最简单方法。

4

2 回答 2

1

我发现答案是使用“@WithUserDetails”注释

@Test
@WithUserDetails("me@example.com")
void registrationWorksThroughAllLayers() throws Exception {

这将使用实现 UserDetailsS​​ervice 的自动装配类,并在上面的代码中使用带注释的值“me@example.com”调用其 loadUserByUsername。

于 2020-07-05T18:06:38.820 回答
0

此设置当前存在冲突。一方面,您为SecurityContext使用提供了一个模拟用户,@WithMockUser另一方面,您为实际身份验证准备了一个有效的 JWT 令牌。

@WithMockUser通常用于测试,例如轻松访问受保护的端点,而无需创建具有正确身份验证信息(如 JWT 或基本身份验证)的请求。

所以你应该选择一种当前的方法:要么去模拟用户,要么生成JWT 并访问你的端点。

您当前不工作的原因@WithMockUser可能与 Spring Security 选择的默认用户名有关。如果您希望它与数据库中的用户匹配,请考虑对其进行配置:@WithMockUser(username="YOUR_USERNAME",roles={"USER","ADMIN"})

要进一步调试您的应用程序,您可以临时添加

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

到您正在测试的端点并对其进行调试以了解哪个用户现在实际上是SecurityContext.

于 2020-06-30T06:01:22.957 回答