-
Notifications
You must be signed in to change notification settings - Fork 1
단위 테스트
sieun edited this page Dec 4, 2024
·
1 revision
저희 프로젝트는 service 레이어에 핵심 로직이 많이 분포되어 있다고 판단하고, 단위 테스트를 service 레이어를 대상으로 진행하기로 결정했습니다.
jest로 테스트 코드를 작성하던 중, service 레이어가 주입 받는 repository나 다른 service를 어떻게 처리해야 할 지 고민이 있었습니다.
testing module을 통해 의존성을 주입하게 되면, 주입된 서비스의 의존성도 주입해야 하는 매우 귀찮은 문제가 생겼습니다.
그래서 아래와 같이 testing module을 만드는 시점에서, repository 및 다른 service 들을 모킹해서 주입해주기로 결정했습니다.
describe('stock order test', () => {
let stockOrderService: StockOrderService;
let stockOrderRepository: StockOrderRepository;
let assetRepository: AssetRepository;
let userStockRepository: UserStockRepository;
beforeEach(async () => {
const mockStockOrderRepository = { // stockOrderRepository mocking
findBy: jest.fn(),
save: jest.fn(),
create: jest.fn(),
findOneBy: jest.fn(),
remove: jest.fn(),
existsBy: jest.fn(),
};
const mockAssetRepository = { findOneBy: jest.fn() }; // assetRepository mocking
const mockStockPriceSocketService = { // stockPriceSocketService mocking
subscribeByCode: jest.fn(),
unsubscribeByCode: jest.fn(),
};
const mockUserStockRepository = { findOneBy: jest.fn() }; // userStockRepository mocking
const module = await Test.createTestingModule({
providers: [
StockOrderService,
{ provide: StockOrderRepository, useValue: mockStockOrderRepository },
{ provide: AssetRepository, useValue: mockAssetRepository },
{
provide: StockPriceSocketService,
useValue: mockStockPriceSocketService,
},
{ provide: UserStockRepository, useValue: mockUserStockRepository },
],
}).compile();
stockOrderService = module.get(StockOrderService);
stockOrderRepository = module.get(StockOrderRepository);
assetRepository = module.get(AssetRepository);
userStockRepository = module.get(UserStockRepository);
});
위와 같이 모킹을 진행한 뒤, 아래와 같이 각 테스트에서 특정 메소드의 리턴 값을 지정해줄 수 있었습니다.
it('충분한 자산을 가지고 특정 주식에 대해 매수를 요청할 경우, 요청이 DB에 정상적으로 등록된다.', async () => {
jest.spyOn(assetRepository, 'findOneBy').mockResolvedValue({
id: 1,
user_id: 1,
stock_balance: 0,
cash_balance: 1000,
total_asset: 1000,
total_profit: 0,
total_profit_rate: 0,
});
// 나머지 테스트 코드...
});
단위 테스트를 진행한 service 레이어에 대한 test coverage는 다음과 같습니다.
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
---|---|---|---|---|---|
asset.service.ts | 85.71 | 50 | 68.42 | 85.24 | 100-104,158-168 |
stock-bookmark.service.ts | 100 | 100 | 100 | 100 | |
stock-detail.service.ts | 94 | 60 | 90.9 | 95.65 | 111,132 |
stock-index.service.ts | 88.57 | 50 | 83.33 | 87.87 | 59-68,118 |
stock-order.service.ts | 84.31 | 90 | 60 | 85.41 | 119-142 |
stock-topfive.service.ts | 81.57 | 20 | 100 | 80.55 | 34-43 |
stock-trade-history.service.ts | 100 | 100 | 100 | 100 |
- [FE] 프론트엔드 기술스택
- [FE] 라이브러리 없이 차트 구현 이유
- [FE] Canvas API 사용방법
- [FE] 네비게이션 바 애니메이션 구현
- [FE] Socket.io 사용방법
- [FE] Tanstack Router에 대하여...
- [FE] Intl(Internationalization) API
- [FE] React Suspense 적용
- [FE] 한글 입력 방식의 유연성을 높인 검색 시스템 구현하기
- [BE] 백엔드 기술 스택
- [BE] SSE vs Socket.io
- [BE] Redis를 도입하게 된 계기
- [BE] ACG Rule을 활용한 Secure CI CD 파이프라인 구현
- [BE] Nginx 로드밸런싱을 통해 한국 투자 API 소켓 제한 극복
- [BE] 주가 지수 기능 개발 과정
- [BE] 매수 및 매도 기능 개발 과정
- [BE] 실시간 자산 조회 기능 개발 과정
- [BE] 단위 테스트
- [BE] redis를 이용한 한국투자 Open API 세션 관리
- [BE] 데이터베이스 인덱싱
- [FE] React에서의 DOM 요소 접근 (useRef vs getElementById)
- [FE] Outlet을 활용한 공통 레이아웃 관리
- [FE] react hooks가 특정 조건에서 실행되면 안되는 이유 & useQuery에 query function 매개변수가 undefined일 수도 있을 때 어떻게 해결할까
- [FE] cross‐domain 로컬 환경에서 cookie로 인증 처리하기 with vite proxy
- [FE] 크롬&사파리 Composition 차이
- [FE] useEffect 의존성 배열
- [BE] Naver Cloud Platform HTTPS 무응답 현상
- [BE] 한국투자 Open API에서 access token을 발급받지 못하는 문제
- [BE] 한국투자 Open API와 웹소켓 연결이 되지 않던 문제
- [BE] 한국투자 Open API 웹소켓 연결이 중단되는 문제
- [BE] 같은 주식 주문이 동시에 여러 번 체결되는 문제
- [BE] 한국투자 Open API Websocket 세션을 두 개에서 한 개로 변경하기
- [BE] Nginx 로드 밸런싱 중 Socket bad Request 발생하는 현상
- [BE] 매수/매도 체결 로직에 의해 redis pub/sub이 정상적으로 동작하지 않는 문제