package com.vincent.rsf.server.ai.mapper; import com.baomidou.mybatisplus.core.MybatisConfiguration; import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean; import com.vincent.rsf.server.ai.entity.AiChatMessage; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.DriverManagerDataSource; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.mybatis.spring.annotation.MapperScan; import javax.sql.DataSource; import java.util.Date; import java.util.List; import java.util.stream.Collectors; import static org.junit.jupiter.api.Assertions.assertEquals; @ExtendWith(SpringExtension.class) @ContextConfiguration(classes = AiChatMessageMapperIntegrationTest.TestConfig.class) class AiChatMessageMapperIntegrationTest { @Autowired private AiChatMessageMapper aiChatMessageMapper; @Autowired private JdbcTemplate jdbcTemplate; @BeforeEach void setUpSchema() { jdbcTemplate.execute("drop table if exists sys_ai_chat_message"); jdbcTemplate.execute(""" create table sys_ai_chat_message ( id bigint auto_increment primary key, session_id bigint, seq_no integer, role varchar(32), content varchar(1000), content_length integer, user_id bigint, tenant_id bigint, deleted integer, create_by bigint, create_time timestamp ) """); } @Test void shouldInsertSelectLatestAndSoftDeleteMessages() { Date now = new Date(); aiChatMessageMapper.insertBatch(List.of( message(10L, 1, "user", "hello", now), message(10L, 2, "assistant", "world", now), message(10L, 2, "assistant", "world latest", now), message(20L, 1, "user", "other", now) )); List latest = aiChatMessageMapper.selectLatestMessagesBySessionIds(List.of(10L, 20L)); assertEquals(List.of(10L, 20L), latest.stream().map(AiChatMessage::getSessionId).sorted().collect(Collectors.toList())); assertEquals("world latest", latest.stream().filter(item -> item.getSessionId().equals(10L)).findFirst().orElseThrow().getContent()); aiChatMessageMapper.softDeleteByIds(List.of(latest.stream().filter(item -> item.getSessionId().equals(20L)).findFirst().orElseThrow().getId())); assertEquals(3, jdbcTemplate.queryForObject("select count(*) from sys_ai_chat_message where deleted = 0", Integer.class)); aiChatMessageMapper.softDeleteBySessionId(10L); assertEquals(0, jdbcTemplate.queryForObject("select count(*) from sys_ai_chat_message where deleted = 0", Integer.class)); } private AiChatMessage message(Long sessionId, int seqNo, String role, String content, Date createTime) { return new AiChatMessage() .setSessionId(sessionId) .setSeqNo(seqNo) .setRole(role) .setContent(content) .setContentLength(content.length()) .setUserId(1L) .setTenantId(1L) .setDeleted(0) .setCreateBy(1L) .setCreateTime(createTime); } @Configuration @MapperScan(basePackageClasses = AiChatMessageMapper.class) static class TestConfig { @Bean DataSource dataSource() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("org.h2.Driver"); dataSource.setUrl("jdbc:h2:mem:ai-chat-message;MODE=MySQL;DB_CLOSE_DELAY=-1"); dataSource.setUsername("sa"); dataSource.setPassword(""); return dataSource; } @Bean JdbcTemplate jdbcTemplate(DataSource dataSource) { return new JdbcTemplate(dataSource); } @Bean MybatisSqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) throws Exception { MybatisSqlSessionFactoryBean factoryBean = new MybatisSqlSessionFactoryBean(); factoryBean.setDataSource(dataSource); factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver() .getResources("classpath*:mapper/ai/*.xml")); MybatisConfiguration configuration = new MybatisConfiguration(); configuration.setMapUnderscoreToCamelCase(true); factoryBean.setConfiguration(configuration); return factoryBean; } } }