@WithMockUser 在并行上下文中
Posted
技术标签:
【中文标题】@WithMockUser 在并行上下文中【英文标题】:@WithMockUser in a parallel context 【发布时间】:2020-11-15 01:25:23 【问题描述】:以下代码只是我想要实现的简化版本。
我正在使用@WithMockUser(username = "jane@no-domain.com", authorities = "ROLE_ADMIN")
在我的测试中模拟用户。
@RunWith(SpringRunner.class)
@SpringBootTest
@EnableAsync
@WithMockUser(username = "jane@no-domain.com", authorities = "ROLE_ADMIN")
public class NonTest
@Test
public void test()
IntStream.range(1, 10)
.parallel() // Comment this and it will work
.forEach(value ->
getUser(value);
);
public void getUser(int value)
System.out.println(value + ": " + ((User) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername());
当我在注释掉.parallel()
的情况下执行上述代码时,它可以正常工作并按预期打印出以下内容:
1: jane@no-domain.com
2: jane@no-domain.com
3: jane@no-domain.com
4: jane@no-domain.com
5: jane@no-domain.com
6: jane@no-domain.com
7: jane@no-domain.com
8: jane@no-domain.com
9: jane@no-domain.com
...但是当我添加.parallel()
时,它会抛出NullPointerException
,因为不知何故被模拟的用户不存在。
当我使用 ExecutorService
或任何类型的线程时,它的行为方式相同。
那么,如何并行执行该方法?
【问题讨论】:
【参考方案1】:.parallel()
的使用将产生多个线程以并行运行流。来自tutorial 直播:
当流并行执行时,Java 运行时将 流成多个子流。聚合操作迭代和 并行处理这些子流,然后合并结果。
所以你需要让子线程从本地线程继承SecurityContextHolder
,为此你可以使用@PostConstruct
,如下所示(查看更多信息here):
@SpringBootTest
@EnableAsync
@WithMockUser(username = "jane@no-domain.com", authorities = "ROLE_ADMIN")
public class NonTest
@Test
public void test()
IntStream.range(1, 10)
.parallel()
.forEach(this::getUser);
@PostConstruct
void setGlobalSecurityContext()
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
public void getUser(int value)
System.out.println(value + ": " + ((User) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername());
输出
6: jane@no-domain.com
7: jane@no-domain.com
1: jane@no-domain.com
2: jane@no-domain.com
3: jane@no-domain.com
9: jane@no-domain.com
4: jane@no-domain.com
8: jane@no-domain.com
5: jane@no-domain.com
【讨论】:
谢谢。那行得通。我也学到了一些东西。我不知道子线程应该从本地线程继承SecurityContext
。以上是关于@WithMockUser 在并行上下文中的主要内容,如果未能解决你的问题,请参考以下文章
Spring boot + webflux:并行运行某些步骤时上下文丢失