Spring 安全,JUnit:@Before 中创建的用户的@WithUserDetails

Spring Security, JUnit: @WithUserDetails for user created in @Before

在使用 Spring MockMVC 的 JUnit 测试中,有两种方法可以作为 Spring 安全用户进行身份验证:@WithMockUser 使用提供的凭据创建一个虚拟用户,@WithUserDetails 获取用户名并使用自定义 UserDetailsServiceUserDetailsServiceImpl)将其解析为正确的自定义 UserDetails 实现。

在我的例子中,UserDetailsService 从数据库加载一个用户。我要使用的用户已插入到测试套件的 @Before 方法中。

但是,我的UserDetailsServiceImpl没有找到用户。

在我的 @Before 中,我这样插入用户:

User u = new User();
u.setEMail("test@test.de");
u = userRepository.save(u);

并且在 UserDetailsServiceImpl 中:

public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    User user = this.userRepository.findOneByEMail(username);

    if (user == null)
        throw new UsernameNotFoundException(String.format("No user found with username '%s'.", username));
    return user;
}

如何将在 @Before 中创建的帐户用于 @WithUserDetails

不幸的是,您无法使用 @Before 轻松完成 @WithUserDetails,因为 Spring @WithUserDetails 注释将在 [之前调用 Spring 安全上下文测试侦听器=22=] setUp 方法与 @Before.

这里是一个小技巧和对你问题的回答。

@Inject
private EntityManager em;

@Inject
PlatformTransactionManager txManager;

@BeforeTransaction
public void setup() {
    new TransactionTemplate(txManager).execute(status -> {

        User u = new User();
        u.setEMail("test@test.de");
        em.save(u);

        return null;
    });
}

@AfterTransaction
public void cleanup() {
    new TransactionTemplate(txManager).execute(status -> {
        // Check if the entity is managed by EntityManager.
        // If not, make it managed with merge() and remove it.
        em.remove(em.contains(u) ? user1 : em.merge(u));
        return null;
    });
}


@Test
@Transactional
@WithUserDetails(value = "test@test.de", userDetailsServiceBeanName = "loadUserByUsername")
public void test() {

}

您可以使用 @PostConstruct 而不是 @Before。那对我有用。有人可以证实吗?

使用setupBefore = TEST_EXECUTION

这将有效地导致 @WithUserDetails@Before@BeforeEach

之后执行
@BeforeEach
public void createUser() {
   ...
}

@Test
@WithUserDetails(value = "username", setupBefore = TestExecutionEvent.TEST_EXECUTION)
public void expectToWork() {
   ...
}