-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[BE] 27.07 주식 주문 서비스 테스트 코드 작성 #237 #245
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,251 @@ | ||
import { Test } from '@nestjs/testing'; | ||
import { | ||
BadRequestException, | ||
ConflictException, | ||
ForbiddenException, | ||
} from '@nestjs/common'; | ||
import { StockOrderService } from './stock-order.service'; | ||
import { StockOrderRepository } from './stock-order.repository'; | ||
import { StockPriceSocketService } from '../../stockSocket/stock-price-socket.service'; | ||
import { UserStockRepository } from '../../asset/user-stock.repository'; | ||
import { AssetRepository } from '../../asset/asset.repository'; | ||
import { TradeType } from './enum/trade-type'; | ||
import { StatusType } from './enum/status-type'; | ||
|
||
describe('stock order test', () => { | ||
let stockOrderService: StockOrderService; | ||
let stockOrderRepository: StockOrderRepository; | ||
let assetRepository: AssetRepository; | ||
let userStockRepository: UserStockRepository; | ||
|
||
beforeEach(async () => { | ||
const mockStockOrderRepository = { | ||
findBy: jest.fn(), | ||
save: jest.fn(), | ||
create: jest.fn(), | ||
findOneBy: jest.fn(), | ||
remove: jest.fn(), | ||
existsBy: jest.fn(), | ||
}; | ||
const mockAssetRepository = { findOneBy: jest.fn() }; | ||
const mockStockPriceSocketService = { | ||
subscribeByCode: jest.fn(), | ||
unsubscribeByCode: jest.fn(), | ||
}; | ||
const mockUserStockRepository = { findOneBy: jest.fn() }; | ||
|
||
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, | ||
}); | ||
|
||
jest.spyOn(stockOrderRepository, 'findBy').mockResolvedValue([]); | ||
|
||
const createMock = jest.fn(); | ||
jest.spyOn(stockOrderRepository, 'create').mockImplementation(createMock); | ||
|
||
const saveMock = jest.fn(); | ||
jest.spyOn(stockOrderRepository, 'save').mockImplementation(saveMock); | ||
|
||
await stockOrderService.buy(1, { | ||
stock_code: '005930', | ||
price: 1000, | ||
amount: 1, | ||
}); | ||
|
||
expect(createMock).toHaveBeenCalledWith({ | ||
user_id: 1, | ||
stock_code: '005930', | ||
trade_type: TradeType.BUY, | ||
amount: 1, | ||
price: 1000, | ||
status: StatusType.PENDING, | ||
}); | ||
expect(saveMock).toHaveBeenCalled(); | ||
}); | ||
|
||
it('자산이 부족한 상태로 특정 주식에 대해 매수를 요청할 경우, BadRequest 예외가 발생한다.', 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, | ||
}); | ||
|
||
jest.spyOn(stockOrderRepository, 'findBy').mockResolvedValue([ | ||
{ | ||
id: 1, | ||
user_id: 1, | ||
stock_code: '005930', | ||
trade_type: TradeType.BUY, | ||
amount: 1, | ||
price: 1000, | ||
status: StatusType.PENDING, | ||
created_at: new Date(), | ||
}, | ||
]); | ||
|
||
await expect( | ||
stockOrderService.buy(1, { | ||
stock_code: '005930', | ||
price: 1000, | ||
amount: 1, | ||
}), | ||
).rejects.toThrow(BadRequestException); | ||
}); | ||
|
||
it('충분한 주식을 가지고 특정 주식에 대해 매도를 요청할 경우, 요청이 DB에 정상적으로 등록된다.', async () => { | ||
jest.spyOn(userStockRepository, 'findOneBy').mockResolvedValue({ | ||
id: 1, | ||
user_id: 1, | ||
stock_code: '005930', | ||
quantity: 1, | ||
avg_price: 1000, | ||
last_updated: new Date(), | ||
}); | ||
|
||
jest.spyOn(stockOrderRepository, 'findBy').mockResolvedValue([]); | ||
|
||
const createMock = jest.fn(); | ||
jest.spyOn(stockOrderRepository, 'create').mockImplementation(createMock); | ||
|
||
const saveMock = jest.fn(); | ||
jest.spyOn(stockOrderRepository, 'save').mockImplementation(saveMock); | ||
|
||
await stockOrderService.sell(1, { | ||
stock_code: '005930', | ||
price: 1000, | ||
amount: 1, | ||
}); | ||
|
||
expect(createMock).toHaveBeenCalledWith({ | ||
user_id: 1, | ||
stock_code: '005930', | ||
trade_type: TradeType.SELL, | ||
amount: 1, | ||
price: 1000, | ||
status: StatusType.PENDING, | ||
}); | ||
expect(saveMock).toHaveBeenCalled(); | ||
}); | ||
|
||
it('주식이 부족한 상태로 특정 주식에 대해 매도를 요청할 경우, BadRequest 예외가 발생한다.', async () => { | ||
jest.spyOn(userStockRepository, 'findOneBy').mockResolvedValue({ | ||
id: 1, | ||
user_id: 1, | ||
stock_code: '005930', | ||
quantity: 1, | ||
avg_price: 1000, | ||
last_updated: new Date(), | ||
}); | ||
|
||
jest.spyOn(stockOrderRepository, 'findBy').mockResolvedValue([ | ||
{ | ||
id: 1, | ||
user_id: 1, | ||
stock_code: '005930', | ||
trade_type: TradeType.SELL, | ||
amount: 1, | ||
price: 1000, | ||
status: StatusType.PENDING, | ||
created_at: new Date(), | ||
}, | ||
]); | ||
|
||
await expect( | ||
stockOrderService.sell(1, { | ||
stock_code: '005930', | ||
price: 1000, | ||
amount: 1, | ||
}), | ||
).rejects.toThrow(BadRequestException); | ||
}); | ||
|
||
it('사용자 본인의 미체결된 주문에 대해 취소를 요청할 경우, 해당 주문이 DB에서 삭제된다.', async () => { | ||
jest.spyOn(stockOrderRepository, 'findOneBy').mockResolvedValue({ | ||
id: 1, | ||
user_id: 1, | ||
stock_code: '005930', | ||
trade_type: TradeType.SELL, | ||
amount: 1, | ||
price: 1000, | ||
status: StatusType.PENDING, | ||
created_at: new Date(), | ||
}); | ||
|
||
const removeMock = jest.fn(); | ||
jest.spyOn(stockOrderRepository, 'remove').mockImplementation(removeMock); | ||
|
||
await stockOrderService.cancel(1, 1); | ||
|
||
expect(removeMock).toHaveBeenCalled(); | ||
}); | ||
|
||
it('사용자 본인의 주문이 아닌 주문에 대해 취소를 요청할 경우, Forbidden 예외가 발생한다.', async () => { | ||
jest.spyOn(stockOrderRepository, 'findOneBy').mockResolvedValue({ | ||
id: 1, | ||
user_id: 2, | ||
stock_code: '005930', | ||
trade_type: TradeType.SELL, | ||
amount: 1, | ||
price: 1000, | ||
status: StatusType.PENDING, | ||
created_at: new Date(), | ||
}); | ||
|
||
const removeMock = jest.fn(); | ||
jest.spyOn(stockOrderRepository, 'remove').mockImplementation(removeMock); | ||
|
||
await expect(stockOrderService.cancel(1, 1)).rejects.toThrow( | ||
ForbiddenException, | ||
); | ||
}); | ||
|
||
it('이미 체결된 주문에 대해 취소를 요청할 경우, Conflict 예외가 발생한다.', async () => { | ||
jest.spyOn(stockOrderRepository, 'findOneBy').mockResolvedValue({ | ||
id: 1, | ||
user_id: 1, | ||
stock_code: '005930', | ||
trade_type: TradeType.SELL, | ||
amount: 1, | ||
price: 1000, | ||
status: StatusType.COMPLETE, | ||
created_at: new Date(), | ||
}); | ||
|
||
const removeMock = jest.fn(); | ||
jest.spyOn(stockOrderRepository, 'remove').mockImplementation(removeMock); | ||
|
||
await expect(stockOrderService.cancel(1, 1)).rejects.toThrow( | ||
ConflictException, | ||
); | ||
}); | ||
}); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🟢 이런 식으로만 하면 되나요?!?!! 저 실시간 체결가 api 테스트 코드 짜는데 자꾸 이런.. 사용하지도 않을 의존성 때문에 에러 뜨고 추가하면 추가한대로 에러 뜨고 해서 진행을 못하고 있었거든요 ㅠㅠㅠㅠ 참고해서 해보겠습니다
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
마자요...... 의존성 타고타고 계속 추가해야되더라구요ㅋㅋㅋ 일단 이렇게 하니까 그 문제는 해결되긴 했어요! 대신 서비스에서 사용하는 메소드들은 mockRepository 같은거 만들때 귀찮지만 아래처럼 선언해줘야 되더라구용