diff --git a/src/main/java/com/mtg/Motugame/stock/service/StockService.java b/src/main/java/com/mtg/Motugame/stock/service/StockService.java index b970745..88fc95f 100644 --- a/src/main/java/com/mtg/Motugame/stock/service/StockService.java +++ b/src/main/java/com/mtg/Motugame/stock/service/StockService.java @@ -1,11 +1,11 @@ package com.mtg.Motugame.stock.service; import com.mtg.Motugame.stock.dto.StockAverageDto; +import com.mtg.Motugame.stock.dto.StockDataInfoDto; import com.mtg.Motugame.stock.dto.StockPriceDto; import java.util.List; public interface StockService { - List getStocksPrices(List seeds); - List getAveragePrices(List seeds); + StockDataInfoDto getStockDataInfoDto(List seeds); } diff --git a/src/main/java/com/mtg/Motugame/stock/service/StockServiceImpl.java b/src/main/java/com/mtg/Motugame/stock/service/StockServiceImpl.java index 6d31e53..e02b63c 100644 --- a/src/main/java/com/mtg/Motugame/stock/service/StockServiceImpl.java +++ b/src/main/java/com/mtg/Motugame/stock/service/StockServiceImpl.java @@ -19,6 +19,7 @@ public class StockServiceImpl implements StockService { private final StockInfoRepository stockInfoRepository; + @Override public StockDataInfoDto getStockDataInfoDto(List seeds) { return StockDataInfoDto.builder() .stockPrices(getStocksPrices(seeds)) @@ -27,7 +28,7 @@ public StockDataInfoDto getStockDataInfoDto(List seeds) { } //주식가격정보를 가져옴 - public List getStocksPrices(List seeds) { + private List getStocksPrices(List seeds) { List stockPriceDtoList = new ArrayList<>(); for (var seed : seeds) { @@ -75,8 +76,7 @@ private List getStockDatePriceDtoList(List return stockDatePriceDtos; } - @Override - public List getAveragePrices(List seeds) { + private List getAveragePrices(List seeds) { List stockAverageDtoList = new ArrayList<>(); List stockPriceDtoList = getStocksPrices(seeds); @@ -107,31 +107,6 @@ private Double getUserAverageProfit(String stockCode) { return totalProfit.divide(new BigDecimal(String.valueOf(stockInfoEntity.getScoreRecords().size())),2).doubleValue(); } - - private List convertSeedsToIndex(List seeds) { - List result = new ArrayList<>(); - for (String seed : seeds) { - String stockIndex = seed.substring(0, 3); - result.add(Integer.parseInt(stockIndex) + ""); - } - return result; - } - - private List getStockDatePriceDtoList(StockInfoEntity stockInfoEntity) { - List stockDatePriceDtos = new ArrayList<>(); - - //주식 코드에 해당하는 가격정보 한달치 entity 리스트를 반환받음 - List stockPriceEntities = stockInfoEntity.getStockPriceEntities(); - - //entity에서 필요한 정보(price, date) 추출 후 list저장 - for (StockPriceEntity entity : stockPriceEntities) { - stockDatePriceDtos.add(StockDatePriceDto.builder() - .price(entity.getClose()) - .date(entity.getDate()).build()); - } - - return stockDatePriceDtos; - } public Integer getStocksInfo() { return stockInfoRepository.findAll().size(); diff --git a/src/test/java/com/mtg/Motugame/stock/controller/StockControllerTest.java b/src/test/java/com/mtg/Motugame/stock/controller/StockControllerTest.java index 61ee05f..5b7645e 100644 --- a/src/test/java/com/mtg/Motugame/stock/controller/StockControllerTest.java +++ b/src/test/java/com/mtg/Motugame/stock/controller/StockControllerTest.java @@ -1,147 +1,183 @@ -//package com.mtg.Motugame.stock.controller; -// -//import com.mtg.Motugame.entity.StockInfoEntity; -//import com.mtg.Motugame.stock.dto.StockDataInfoDto; -//import com.mtg.Motugame.stock.dto.StockDatePriceDto; -//import com.mtg.Motugame.stock.service.StockServiceImpl; -//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.AutoConfigureMockMvc; -//import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -//import org.springframework.boot.test.mock.mockito.MockBean; -//import org.springframework.data.jpa.mapping.JpaMetamodelMappingContext; -//import org.springframework.test.web.servlet.MockMvc; -// -//import static org.mockito.BDDMockito.given; -//import static org.mockito.Mockito.atLeastOnce; -//import static org.mockito.Mockito.verify; -//import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -//import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.head; -//import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -//import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; -// -//import java.math.BigDecimal; -//import java.time.LocalDate; -//import java.util.ArrayList; -//import java.util.Arrays; -//import java.util.List; -// -//@WebMvcTest(StockController.class) -//@AutoConfigureMockMvc -//@MockBean(JpaMetamodelMappingContext.class) -//class StockControllerTest { -// -// @MockBean -// private StockServiceImpl stockService; -// -// @Autowired -// private MockMvc mockMvc; -// -// @Test -// @DisplayName("랜덤주식 데이터 가져오기 성공") -// public void getRandomStockSuccess() throws Exception{ -// //given -// //인덱스 번호 지정 -// List indices = new ArrayList<>(); -// indices.add("0011"); -// indices.add("0021"); -// -// //요청 데이터(주식가격리스트) 설정 -// List stockDatePriceDtoList = new ArrayList<>(); -// stockDatePriceDtoList.add(StockDatePriceDto.builder() -// .date(LocalDate.now()) -// .price(new BigDecimal(10000)).build()); -// stockDatePriceDtoList.add(StockDatePriceDto.builder() -// .date(LocalDate.now().minusDays(1)) -// .price(new BigDecimal(20000)).build()); -// -// //요청 데이터 (주식코드,주식이름) + 주식가격리스트 -// List stockPriceDtoList = new ArrayList<>(); -// stockPriceDtoList.add(StockPriceDto.builder() -// .stockCode("035420") -// .stockName("네이버") -// .datas(stockDatePriceDtoList).build()); -// -// given(stockService.getStocksPrices(indices)).willReturn(stockPriceDtoList); -// -// //when -// mockMvc.perform(get("/api/stocks?index=0011&index=0021")) -// .andExpect(status().isOk()) -// .andExpect(jsonPath("$.[0].stockCode").exists()) -// .andExpect(jsonPath("$.[0].stockName").exists()) -// .andExpect(jsonPath("$.[0].datas").exists()) -// .andDo(print()); -// //then -// verify(stockService).getStocksPrices(indices); -// } -// -// @Test -// @DisplayName("랜덤주식 데이터 가져오기 실패") -// public void getRandomStockfail() throws Exception{ -// //given -// -// //랜덤 인덱스 번호 지정 -// List indices = new ArrayList<>(); -// indices.add("0011"); -// indices.add("0021"); -// -// //요청 데이터 주식가격 설정 -// List stockDatePriceDtoList = new ArrayList<>(); -// stockDatePriceDtoList.add(StockDatePriceDto.builder() -// .date(LocalDate.now()) -// .price(new BigDecimal(10000)).build()); -// stockDatePriceDtoList.add(StockDatePriceDto.builder() -// .date(LocalDate.now().minusDays(1)) -// .price(new BigDecimal(20000)).build()); -// -// //요청 데이터 (주식코드,주식이름) + 주식가격리스트 -// List stockPriceDtoList = new ArrayList<>(); -// stockPriceDtoList.add(StockPriceDto.builder() -// .stockCode("035420") -// .stockName("네이버") -// .datas(stockDatePriceDtoList).build()); -// -// given(stockService.getStocksPrices(indices)).willReturn(stockPriceDtoList); -// -// //when -// mockMvc.perform(get("/api/stocks?seed=0011&seed=0021"))//1,26과 불일치하므로 비어있는 body 체크 -// .andExpect(status().isOk()) -// .andExpect(jsonPath("$.[0]").doesNotExist()) -// .andDo(print()); -// //then -// verify(stockService, atLeastOnce()).getStocksPrices(Arrays.asList("0011","0021"));//정상적으로 동작했는지 검증 -// } -// -// @Test -// @DisplayName("헤더에 주식데이터 개수 담기 성공") -// public void getHeadRandomStockSuccess() throws Exception{ -// //given -// -// //요청 데이터 (주식코드,주식이름) + 주식가격리스트 -// List stockDataInfoList = stockInfoList(); -// -// given(stockService.getStocksInfo()).willReturn(stockDataInfoList.size()); -// -// //when -// mockMvc.perform(head("/api/stocks")) //request의 헤더에 추가하는 것이다. -// .andExpect(header().exists("X-Total-Count")) -// .andExpect(status().isOk()) -// .andDo(print()); -// -// //then -// verify(stockService).getStocksInfo(); -// } -// -// private List stockInfoList(){ -// List stockInfoEntityList = new ArrayList<>(); -// for (int i = 0; i < 20; i++) { -// stockInfoEntityList.add(StockInfoEntity.builder() -// .stockCode(Integer.toString(i)) -// .stockName("test name") -// .build() -// ); -// } -// return stockInfoEntityList; -// } -//} +package com.mtg.Motugame.stock.controller; + +import com.mtg.Motugame.entity.StockInfoEntity; +import com.mtg.Motugame.stock.dto.StockAverageDto; +import com.mtg.Motugame.stock.dto.StockDataInfoDto; +import com.mtg.Motugame.stock.dto.StockDatePriceDto; +import com.mtg.Motugame.stock.dto.StockPriceDto; +import com.mtg.Motugame.stock.service.StockServiceImpl; +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.AutoConfigureMockMvc; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.data.jpa.mapping.JpaMetamodelMappingContext; +import org.springframework.test.web.servlet.MockMvc; + +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.verify; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.head; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +@WebMvcTest(StockController.class) +@AutoConfigureMockMvc +@MockBean(JpaMetamodelMappingContext.class) +class StockControllerTest { + + @MockBean + private StockServiceImpl stockService; + + @Autowired + private MockMvc mockMvc; + + @Test + @DisplayName("랜덤주식 데이터 가져오는 api 정상동작 확인") + public void getRandomStockSuccess() throws Exception{ + //given + //인덱스 번호 지정 + List seeds = new ArrayList<>(); + seeds.add("0011"); + seeds.add("2002"); + seeds.add("4004"); + + //각 주식의 평균 수익률 정보 + List stockAverageDtoList = new ArrayList<>(); + + StockAverageDto stockAverageDto1 = StockAverageDto.builder() + .stockName("삼성전자") + .userAverageProfit(3.32).build(); + StockAverageDto stockAverageDto2 = StockAverageDto.builder() + .stockName("플랙티컬") + .userAverageProfit(100.32).build(); + StockAverageDto stockAverageDto3 = StockAverageDto.builder() + .stockName("CJ") + .userAverageProfit(2.32).build(); + + stockAverageDtoList.add(stockAverageDto1); + stockAverageDtoList.add(stockAverageDto2); + stockAverageDtoList.add(stockAverageDto3); + + //각 주식의 가격 정보 + List stockPriceDtoList = new ArrayList<>(); + + List datas1 = new ArrayList<>(); + datas1.add(StockDatePriceDto.builder() + .date(LocalDate.now()) + .price(BigDecimal.valueOf(100.12)).build()); + datas1.add(StockDatePriceDto.builder() + .date(LocalDate.now().plusDays(1)) + .price(BigDecimal.valueOf(200.12)).build()); + StockPriceDto stockPriceDto1 = StockPriceDto.builder() + .stockName("삼성전자") + .stockCode("005930") + .datas(datas1).build(); + + List datas2 = new ArrayList<>(); + datas2.add(StockDatePriceDto.builder() + .date(LocalDate.now()) + .price(BigDecimal.valueOf(100.12)).build()); + datas2.add(StockDatePriceDto.builder() + .date(LocalDate.now().plusDays(1)) + .price(BigDecimal.valueOf(200.12)).build()); + StockPriceDto stockPriceDto2 = StockPriceDto.builder() + .stockName("플랙티컬") + .stockCode("000001") + .datas(datas2).build(); + + List datas3 = new ArrayList<>(); + datas3.add(StockDatePriceDto.builder() + .date(LocalDate.now()) + .price(BigDecimal.valueOf(100.12)).build()); + datas3.add(StockDatePriceDto.builder() + .date(LocalDate.now().plusDays(1)) + .price(BigDecimal.valueOf(200.12)).build()); + StockPriceDto stockPriceDto3 = StockPriceDto.builder() + .stockName("CJ") + .stockCode("001040") + .datas(datas3).build(); + + stockPriceDtoList.add(stockPriceDto1); + stockPriceDtoList.add(stockPriceDto2); + stockPriceDtoList.add(stockPriceDto3); + + //각 게임에 필요한 모든 주식정보를 담음 + StockDataInfoDto stockDataInfoDto = StockDataInfoDto.builder() + .stockAverages(stockAverageDtoList) + .stockPrices(stockPriceDtoList).build(); + + given(stockService.getStockDataInfoDto(seeds)).willReturn(stockDataInfoDto); + + //when + mockMvc.perform(get("/api/stocks?seed=0011&seed=2002&seed=4004")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.stockAverages[0].stockName").exists()) + .andExpect(jsonPath("$.stockAverages[0].userAverageProfit").exists()) + .andExpect(jsonPath("$.stockPrices[0].stockCode").exists()) + .andExpect(jsonPath("$.stockPrices[0].stockName").exists()) + .andExpect(jsonPath("$.stockPrices[0].datas[0].date").exists()) + .andExpect(jsonPath("$.stockPrices[0].datas[0].price").exists()) + .andExpect(jsonPath("$.stockPrices[0].datas[1].date").exists()) + .andExpect(jsonPath("$.stockPrices[0].datas[1].price").exists()) + .andExpect(jsonPath("$.stockAverages[1].stockName").exists()) + .andExpect(jsonPath("$.stockAverages[1].userAverageProfit").exists()) + .andExpect(jsonPath("$.stockPrices[1].stockCode").exists()) + .andExpect(jsonPath("$.stockPrices[1].stockName").exists()) + .andExpect(jsonPath("$.stockPrices[1].datas[0].date").exists()) + .andExpect(jsonPath("$.stockPrices[1].datas[0].price").exists()) + .andExpect(jsonPath("$.stockPrices[1].datas[1].date").exists()) + .andExpect(jsonPath("$.stockPrices[1].datas[1].price").exists()) + .andExpect(jsonPath("$.stockAverages[2].stockName").exists()) + .andExpect(jsonPath("$.stockAverages[2].userAverageProfit").exists()) + .andExpect(jsonPath("$.stockPrices[2].stockCode").exists()) + .andExpect(jsonPath("$.stockPrices[2].stockName").exists()) + .andExpect(jsonPath("$.stockPrices[2].datas[0].date").exists()) + .andExpect(jsonPath("$.stockPrices[2].datas[0].price").exists()) + .andExpect(jsonPath("$.stockPrices[2].datas[1].date").exists()) + .andExpect(jsonPath("$.stockPrices[2].datas[1].price").exists()) + .andDo(print()); + //then + verify(stockService).getStockDataInfoDto(seeds); + } + + @Test + @DisplayName("헤더에 주식데이터 개수 담기 성공") + public void getHeadRandomStockSuccess() throws Exception{ + //given + + //요청 데이터 (주식코드,주식이름) + 주식가격리스트 + List stockDataInfoList = stockInfoList(); + + given(stockService.getStocksInfo()).willReturn(stockDataInfoList.size()); + + //when + mockMvc.perform(head("/api/stocks")) //request의 헤더에 추가하는 것이다. + .andExpect(header().exists("X-Total-Count")) + .andExpect(status().isOk()) + .andDo(print()); + + //then + verify(stockService).getStocksInfo(); + } + + private List stockInfoList(){ + List stockInfoEntityList = new ArrayList<>(); + for (int i = 0; i < 20; i++) { + stockInfoEntityList.add(StockInfoEntity.builder() + .stockCode(Integer.toString(i)) + .stockName("test name") + .build() + ); + } + return stockInfoEntityList; + } +} diff --git a/src/test/java/com/mtg/Motugame/stock/repository/StockInfoRepositoryTest.java b/src/test/java/com/mtg/Motugame/stock/repository/StockInfoRepositoryTest.java index d7e1fd1..68ebe1e 100644 --- a/src/test/java/com/mtg/Motugame/stock/repository/StockInfoRepositoryTest.java +++ b/src/test/java/com/mtg/Motugame/stock/repository/StockInfoRepositoryTest.java @@ -58,4 +58,27 @@ public void findSortAllData() { Assertions.assertThat(findStocks.get(0).getStockName()).isEqualTo("SK하이닉스"); } + @Test + @DisplayName("주식 코드로 주식정보 찾기 테스트") + public void findByStockCodeTest() { + //given + StockInfoEntity stockInfo1 = StockInfoEntity.builder() + .stockCode("2") + .stockName("삼성전자") + .build(); + StockInfoEntity stockInfo2 = StockInfoEntity.builder() + .stockCode("1") + .stockName("SK하이닉스") + .build(); + stockInfoRepository.save(stockInfo1); + stockInfoRepository.save(stockInfo2); + + //when + StockInfoEntity findStock = stockInfoRepository.findByStockCode("2"); + + //then + Assertions.assertThat(findStock.getStockCode()).isEqualTo("2"); + Assertions.assertThat(findStock.getStockName()).isEqualTo("삼성전자"); + } + } \ No newline at end of file diff --git a/src/test/java/com/mtg/Motugame/stock/service/StockServiceImplTest.java b/src/test/java/com/mtg/Motugame/stock/service/StockServiceImplTest.java index 14ace96..83d6d65 100644 --- a/src/test/java/com/mtg/Motugame/stock/service/StockServiceImplTest.java +++ b/src/test/java/com/mtg/Motugame/stock/service/StockServiceImplTest.java @@ -1,13 +1,17 @@ package com.mtg.Motugame.stock.service; +import com.mtg.Motugame.entity.ScoreRecordEntity; import com.mtg.Motugame.entity.StockInfoEntity; import com.mtg.Motugame.entity.StockPriceEntity; +import com.mtg.Motugame.stock.dto.StockDataInfoDto; import com.mtg.Motugame.stock.repository.StockInfoRepository; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; + import static org.mockito.BDDMockito.given; + import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; @@ -37,8 +41,8 @@ void getStocksInfoSuccess() { //then Assertions.assertThat(size).isEqualTo(20); } - - private List stockInfoList(){ + + private List stockInfoList() { List stockInfoEntityList = new ArrayList<>(); for (int i = 0; i < 20; i++) { stockInfoEntityList.add(StockInfoEntity.builder() @@ -50,16 +54,79 @@ private List stockInfoList(){ return stockInfoEntityList; } - private List stockInfoEntityList() { + @DisplayName("주식데이터 가져오기 성공") + @Test + public void getStockDataInfoSuccess() throws Exception { + //given + //parameter seed List + List seeds = new ArrayList<>(); + seeds.add("0001"); + seeds.add("0011"); + + //mocking + List stockInfoEntityList = createStockInfoEntity(); + given(stockInfoRepository.findAllByOrderByStockCode()).willReturn(stockInfoEntityList); + given(stockInfoRepository.findByStockCode("0001")).willReturn(stockInfoEntityList.get(0)); + given(stockInfoRepository.findByStockCode("0011")).willReturn(stockInfoEntityList.get(1)); + + + //when + StockDataInfoDto stockDataInfoDto = stockService.getStockDataInfoDto(seeds); + + //then + Assertions.assertThat(stockDataInfoDto.getStockAverages().get(0).getStockName()).isEqualTo("주식1"); + Assertions.assertThat(stockDataInfoDto.getStockAverages().get(0).getUserAverageProfit()).isEqualTo(10.0); + Assertions.assertThat(stockDataInfoDto.getStockPrices().get(0).getStockName()).isEqualTo("주식1"); + Assertions.assertThat(stockDataInfoDto.getStockPrices().get(0).getStockCode()).isEqualTo("0001"); + Assertions.assertThat(stockDataInfoDto.getStockPrices().get(0).getDatas().get(0).getPrice()).isEqualTo(BigDecimal.valueOf(10.0)); + Assertions.assertThat(stockDataInfoDto.getStockPrices().get(0).getDatas().get(0).getDate()).isEqualTo(LocalDate.of(2023,1,1)); + Assertions.assertThat(stockDataInfoDto.getStockPrices().get(0).getDatas().size()).isEqualTo(300); + + Assertions.assertThat(stockDataInfoDto.getStockAverages().get(1).getStockName()).isEqualTo("주식2"); + Assertions.assertThat(stockDataInfoDto.getStockAverages().get(1).getUserAverageProfit()).isEqualTo(10.0); + Assertions.assertThat(stockDataInfoDto.getStockPrices().get(1).getStockName()).isEqualTo("주식2"); + Assertions.assertThat(stockDataInfoDto.getStockPrices().get(1).getStockCode()).isEqualTo("0011"); + Assertions.assertThat(stockDataInfoDto.getStockPrices().get(1).getDatas().get(0).getPrice()).isEqualTo(BigDecimal.valueOf(10.0)); + Assertions.assertThat(stockDataInfoDto.getStockPrices().get(1).getDatas().get(0).getDate()).isEqualTo(LocalDate.of(2023,1,1)); + Assertions.assertThat(stockDataInfoDto.getStockPrices().get(1).getDatas().size()).isEqualTo(300); + } + + //StockInfoEntity 생성 메서드 + private List createStockInfoEntity() { List stockInfoEntityList = new ArrayList<>(); - for (int i = 0; i <= 20; i++) { - stockInfoEntityList.add(StockInfoEntity.builder() - .stockCode("test code") - .stockName("test name") - .stockPriceEntities(stockPriceEntityList()) - .build() - ); + + //StockPriceEntity List 생성 + List stockPriceEntityList = new ArrayList<>(); + for (int i = 0; i < 1000; i++) { + StockPriceEntity stockPriceEntity1 = StockPriceEntity.builder() + .close(BigDecimal.valueOf(10.0)) + .date(LocalDate.of(2023,1,1)).build(); + stockPriceEntityList.add(stockPriceEntity1); + } + + //ScoreRecordEntity List 생성 + List scoreRecordEntityList = new ArrayList<>(); + for (int i = 0; i < 10; i++) { + scoreRecordEntityList.add(ScoreRecordEntity.builder() + .profit(BigDecimal.valueOf(10.0)).build()); } + + //StockInfoEntity List 생성 + stockInfoEntityList.add(StockInfoEntity.builder() + .stockCode("0001") + .stockName("주식1") + .stockPriceEntities(stockPriceEntityList) + .scoreRecords(scoreRecordEntityList) + .build() + ); + stockInfoEntityList.add(StockInfoEntity.builder() + .stockCode("0011") + .stockName("주식2") + .stockPriceEntities(stockPriceEntityList) + .scoreRecords(scoreRecordEntityList) + .build() + ); + return stockInfoEntityList; }