mirror of
https://github.com/hwanny1128/HGZero.git
synced 2026-06-13 07:09:09 +00:00
STT 테스트 환경 구성 및 유저스토리 업데이트
- docker-compose.test.yml 추가: 테스트용 컨테이너 환경 구성 - STT 테스트 설정 및 컨트롤러 테스트 코드 추가 - application.yml 업데이트 - 테스트 스크립트 추가 - 유저스토리 문서 업데이트 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
package com.unicorn.hgzero.stt.config;
|
||||
|
||||
import com.unicorn.hgzero.stt.event.publisher.EventPublisher;
|
||||
import com.unicorn.hgzero.stt.repository.jpa.RecordingRepository;
|
||||
import com.unicorn.hgzero.stt.repository.jpa.SpeakerRepository;
|
||||
import com.unicorn.hgzero.stt.repository.jpa.TranscriptionRepository;
|
||||
import com.unicorn.hgzero.stt.repository.jpa.TranscriptSegmentRepository;
|
||||
import com.unicorn.hgzero.stt.service.RecordingService;
|
||||
import com.unicorn.hgzero.stt.service.SpeakerService;
|
||||
import com.unicorn.hgzero.stt.service.TranscriptionService;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.domain.EntityScan;
|
||||
import org.springframework.boot.test.context.TestConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import redis.embedded.RedisServer;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.PreDestroy;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* 테스트용 설정 클래스
|
||||
* Embedded Redis 서버와 Mock Bean들을 제공
|
||||
*/
|
||||
@TestConfiguration
|
||||
@EnableJpaRepositories(basePackages = "com.unicorn.hgzero.stt.repository.jpa")
|
||||
@EntityScan(basePackages = "com.unicorn.hgzero.stt.repository.entity")
|
||||
@ComponentScan(basePackages = {"com.unicorn.hgzero.stt.service", "com.unicorn.hgzero.stt.config"})
|
||||
public class TestConfig {
|
||||
|
||||
private RedisServer redisServer;
|
||||
|
||||
@PostConstruct
|
||||
public void startRedis() {
|
||||
try {
|
||||
redisServer = new RedisServer(6370);
|
||||
redisServer.start();
|
||||
} catch (Exception e) {
|
||||
// Redis 서버 시작 실패 시 로그만 남기고 계속 진행
|
||||
System.err.println("Failed to start embedded Redis server: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void stopRedis() {
|
||||
if (redisServer != null && redisServer.isActive()) {
|
||||
redisServer.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Primary
|
||||
public EventPublisher eventPublisher() {
|
||||
return mock(EventPublisher.class);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Bean
|
||||
@Primary
|
||||
@ConditionalOnMissingBean
|
||||
public RedisConnectionFactory redisConnectionFactory() {
|
||||
// Embedded Redis에 연결하는 실제 ConnectionFactory
|
||||
return new LettuceConnectionFactory("localhost", 6370);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Primary
|
||||
@ConditionalOnMissingBean
|
||||
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
|
||||
RedisTemplate<String, Object> template = new RedisTemplate<>();
|
||||
template.setConnectionFactory(connectionFactory);
|
||||
return template;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.unicorn.hgzero.stt.config;
|
||||
|
||||
import org.springframework.boot.test.context.TestConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import redis.embedded.RedisServer;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.PreDestroy;
|
||||
|
||||
/**
|
||||
* WebMvcTest용 최소한의 설정 클래스
|
||||
* Repository는 MockBean으로 별도 처리
|
||||
*/
|
||||
@TestConfiguration
|
||||
@ComponentScan(basePackages = "com.unicorn.hgzero.stt.config")
|
||||
public class WebMvcTestConfig {
|
||||
|
||||
private RedisServer redisServer;
|
||||
|
||||
@PostConstruct
|
||||
public void startRedis() {
|
||||
try {
|
||||
redisServer = new RedisServer(6371); // 다른 포트 사용
|
||||
redisServer.start();
|
||||
} catch (Exception e) {
|
||||
System.err.println("Failed to start embedded Redis server: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void stopRedis() {
|
||||
if (redisServer != null && redisServer.isActive()) {
|
||||
redisServer.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Primary
|
||||
public RedisConnectionFactory redisConnectionFactory() {
|
||||
return new LettuceConnectionFactory("localhost", 6371);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Primary
|
||||
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
|
||||
RedisTemplate<String, Object> template = new RedisTemplate<>();
|
||||
template.setConnectionFactory(connectionFactory);
|
||||
return template;
|
||||
}
|
||||
}
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
package com.unicorn.hgzero.stt.controller;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.unicorn.hgzero.stt.dto.RecordingDto;
|
||||
import com.unicorn.hgzero.stt.service.RecordingService;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
|
||||
|
||||
/**
|
||||
* 간단한 녹음 컨트롤러 테스트
|
||||
*/
|
||||
@WebMvcTest(RecordingController.class)
|
||||
@DisplayName("간단한 녹음 컨트롤러 테스트")
|
||||
class SimpleRecordingControllerTest {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@MockBean
|
||||
private RecordingService recordingService;
|
||||
|
||||
private RecordingDto.PrepareRequest prepareRequest;
|
||||
private RecordingDto.PrepareResponse prepareResponse;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
prepareRequest = RecordingDto.PrepareRequest.builder()
|
||||
.meetingId("MEETING-001")
|
||||
.sessionId("SESSION-001")
|
||||
.language("ko-KR")
|
||||
.build();
|
||||
|
||||
prepareResponse = RecordingDto.PrepareResponse.builder()
|
||||
.recordingId("REC-20250123-001")
|
||||
.sessionId("SESSION-001")
|
||||
.status("READY")
|
||||
.streamUrl("wss://api.example.com/stt/v1/ws/stt/SESSION-001")
|
||||
.storagePath("recordings/MEETING-001/SESSION-001.wav")
|
||||
.estimatedInitTime(1100)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("녹음 준비 API 성공")
|
||||
void prepareRecording_Success() throws Exception {
|
||||
// Given
|
||||
when(recordingService.prepareRecording(any(RecordingDto.PrepareRequest.class)))
|
||||
.thenReturn(prepareResponse);
|
||||
|
||||
// When & Then
|
||||
mockMvc.perform(post("/api/v1/stt/recordings/prepare")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(prepareRequest)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.success").value(true))
|
||||
.andExpect(jsonPath("$.data.recordingId").value("REC-20250123-001"))
|
||||
.andExpect(jsonPath("$.data.sessionId").value("SESSION-001"))
|
||||
.andExpect(jsonPath("$.data.status").value("READY"));
|
||||
|
||||
verify(recordingService).prepareRecording(any(RecordingDto.PrepareRequest.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("녹음 시작 API 성공")
|
||||
void startRecording_Success() throws Exception {
|
||||
// Given
|
||||
String recordingId = "REC-20250123-001";
|
||||
RecordingDto.StartRequest startRequest = RecordingDto.StartRequest.builder()
|
||||
.startedBy("user001")
|
||||
.build();
|
||||
|
||||
RecordingDto.StatusResponse statusResponse = RecordingDto.StatusResponse.builder()
|
||||
.recordingId(recordingId)
|
||||
.status("RECORDING")
|
||||
.startTime(LocalDateTime.now())
|
||||
.duration(0)
|
||||
.build();
|
||||
|
||||
when(recordingService.startRecording(eq(recordingId), any(RecordingDto.StartRequest.class)))
|
||||
.thenReturn(statusResponse);
|
||||
|
||||
// When & Then
|
||||
mockMvc.perform(post("/api/v1/stt/recordings/{recordingId}/start", recordingId)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(objectMapper.writeValueAsString(startRequest)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.success").value(true))
|
||||
.andExpect(jsonPath("$.data.recordingId").value(recordingId))
|
||||
.andExpect(jsonPath("$.data.status").value("RECORDING"));
|
||||
|
||||
verify(recordingService).startRecording(eq(recordingId), any(RecordingDto.StartRequest.class));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user