You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot集成Spring Session单元测试Authentication为空问题求助

解决Spring Session Redis + Spring Security测试时Authentication为空的问题

我碰到过类似的情况,结合你的代码和错误信息,问题主要出在三个地方:配置冲突、密码编码器缺失、测试环境会话存储的问题。下面一步步来解决:

1. 修复Spring Security的密码编码器问题

首先,Spring Boot 1.5.x对应的Spring Security 4.x中,inMemoryAuthentication默认要求配置密码编码器,否则登录请求会因为密码不匹配而失败,这会直接导致SecurityContext里没有Authentication对象。

修改你的AppConfiguration类,添加密码编码器(注意:生产环境不要用NoOpPasswordEncoder,这里只是为了测试明文密码):

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.inMemoryAuthentication()
            .passwordEncoder(NoOpPasswordEncoder.getInstance())
            .withUser("user").password("0000").roles("USER");
}

2. 移除冲突的会话配置

你同时使用了@EnableRedisHttpSession注解和spring.session.store-type=redis配置,在Spring Boot 1.5.x版本中这两个配置会冲突,导致SessionRepository的初始化异常,进而会话无法被正确创建和存储。

直接删除application.properties中的spring.session.store-type=redis这一行即可。

3. 解决测试环境的会话存储问题

单元测试时默认没有Redis服务,Spring Session无法将会话存入Redis,导致SecurityContext无法被持久化,断言时就会出现Authentication为空的情况。这里有两种解决方式:

方式一:使用嵌入式Redis进行测试

添加嵌入式Redis的测试依赖(Maven为例):

<dependency>
    <groupId>com.github.kstyrc</groupId>
    <artifactId>embedded-redis</artifactId>
    <version>0.6</version>
    <scope>test</scope>
</dependency>

然后在测试类中启动和停止嵌入式Redis:

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class DemoRedisDataSessionApplicationTests {

    @Autowired
    private MockMvc mockMvc;

    private RedisServer redisServer;

    @Before
    public void setUp() throws IOException {
        // 启动嵌入式Redis,默认端口6379
        redisServer = new RedisServer(6379);
        redisServer.start();
    }

    @After
    public void tearDown() {
        // 测试结束后停止Redis
        redisServer.stop();
    }

    @Test
    public void testUserShouldBeAuthenticated() throws Exception {
        mockMvc.perform(formLogin().user("user").password("0000"))
                .andExpect(status().is3xxRedirection())
                // 明确指定断言用户名,更精准
                .andExpect(authenticated().withUsername("user"));
    }
}

方式二:测试时使用内存会话(无需Redis)

如果不想依赖Redis,可以创建测试专用的会话配置,用内存存储会话:

创建测试配置类:

@Configuration
@EnableHttpSession
public class TestSessionConfiguration {

    @Bean
    public SessionRepository<? extends Session> sessionRepository() {
        // 使用内存版的SessionRepository
        return new MapSessionRepository(new ConcurrentHashMap<>());
    }
}

然后在测试类中引入这个配置:

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
@Import(TestSessionConfiguration.class)
public class DemoRedisDataSessionApplicationTests {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void testUserShouldBeAuthenticated() throws Exception {
        mockMvc.perform(formLogin().user("user").password("0000"))
                .andExpect(status().is3xxRedirection())
                .andExpect(authenticated().withUsername("user"));
    }
}

按照上面的步骤修改后,你的测试应该就能通过了,登录后的SecurityContext会正确存储到会话中,断言时就能获取到Authentication对象。

内容的提问来源于stack exchange,提问作者Fabio Maffioletti

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:51:57