Spring Security,JUnit:@WithUserDetails 用于在 @Before 中创建的用户
Posted
技术标签:
【中文标题】Spring Security,JUnit:@WithUserDetails 用于在 @Before 中创建的用户【英文标题】:Spring Security, JUnit: @WithUserDetails for user created in @Before 【发布时间】:2017-07-16 22:57:53 【问题描述】:在使用 Spring MockMVC 的 JUnit 测试中,有两种方法可以作为 Spring Security 用户进行身份验证:@WithMockUser
使用提供的凭据创建一个虚拟用户,@WithUserDetails
获取用户名并将其解析为正确的自定义 @987654324使用自定义UserDetailsService
(UserDetailsServiceImpl
)实现@。
就我而言,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
一起使用?
【问题讨论】:
这个 *** 的答案很有启发性:Spring Test & Security: How to mock authentication? 【参考方案1】:使用setupBefore = TEST_EXECUTION
这将有效地导致@WithUserDetails
在@Before
和@BeforeEach
之后执行
@BeforeEach
public void createUser()
...
@Test
@WithUserDetails(value = "username", setupBefore = TestExecutionEvent.TEST_EXECUTION)
public void expectToWork()
...
【讨论】:
【参考方案2】:您可以使用@PostConstruct
代替@Before
。这对我有用。有人可以确认吗?
【讨论】:
这工作正常。任何人都知道任何副作用,到目前为止我没有看到...?【参考方案3】:不幸的是,@WithUserDetails
和 @Before
不能轻易做到,因为 Spring @WithUserDetails
注释会在运行 setUp
方法和 @Before
之前调用 Spring 安全上下文测试侦听器。
这里是https://***.com/a/38282258/1814524 的一个小技巧并回答您的问题。
【讨论】:
注意:如果您使用事务,则需要手动删除@AfterTransaction
的内容。它们不会像 @Before
那样自动回滚。
2021 更新:setupBefore = TEST_EXECUTION
对我有用。看我的回答。【参考方案4】:
@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()
【讨论】:
以上是关于Spring Security,JUnit:@WithUserDetails 用于在 @Before 中创建的用户的主要内容,如果未能解决你的问题,请参考以下文章
JUnit 4 & Spring Boot - 在测试前有选择地重新加载上下文/重新加载 Spring Security 配置
如何使用 Spring Security 管理 Spring Boot 中的会话?
org.springframework.security.core.userdetails.User 不能转换为 MyUserDetails (Junit 5)