/**
*
* 2. 상세 페이지 투표하기
* @param postIdx
* @param createPollDto
* @returns
*/
async createPostPoll(
userIdx: UUID,
postIdx: UUID,
createPollDto: CreatePollDto,
) {
const { proInputValue, conInputValue }: CreatePollDto = createPollDto;
const input: boolean = proInputValue || conInputValue;
const inputTransVal: string = proInputValue
? '7'
: conInputValue
? '8'
: null;
if (input) {
const isPoll: Prefers = await this.prefersRepository.findOne({
where: { userIdx, postIdx },
});
if (isPoll) {
const { selectprefer } = isPoll;
if (selectprefer == '7' && conInputValue == true) {
return '이미 찬성에 투표 했습니다.';
} else if (selectprefer == '8' && proInputValue == true) {
return '이미 반대에 투표 했습니다.';
}
}
if (!isPoll) {
await this.prefersRepository.save({
userIdx,
postIdx,
selectprefer: inputTransVal,
});
} else {
await this.prefersRepository
.createQueryBuilder()
.delete()
.from(Prefers)
.where(
'postIdx = :postIdx AND userIdx = :userIdx AND selectprefer = :inputTransVal',
{ postIdx, userIdx, inputTransVal },
)
.execute();
}
const count = await this.prefersRepository
.createQueryBuilder('p')
.where('p.postIdx = :postIdx', { postIdx })
.select([
`COUNT(CASE WHEN p.selectprefer = 7 THEN 1 END) as proCount`,
`COUNT(CASE WHEN p.selectprefer = 8 THEN 1 END) as conCount`,
])
.getRawOne();
return count;
}
}
createPostPoll 메서드에서 시도해 볼 만한 유닛테스트를 연습해보자.
이미 찬성에 투표했는데 반대에 투표하는 경우
유저가 이미 찬성 투표를 한 상태이기 때문에 findOne을 호출하면 반환 값이 const poll = { selectprefer: '7' };
이어야 한다.
jest.spyOn(prefersRepository, 'findOne').mockResolvedValue(poll);
유저는 이미 찬성을 한 상태이지만 모종의 이유로 반대에 투표하고 싶어하는 상황이므로 const createPollDto = { proInputValue: false, conInputValue: true };
로 conInputValue가 true인 상황이다.
그러므로 result의 값은 toEqual의 message 값과 일치할 것이다.
expect(result).toEqual('이미 찬성에 투표 했습니다.');
이미 반대에 투표했는데 찬성에 투표하는 경우 [ 같은 경우이므로 생략 ]
투표에 찬성한 유저가 찬성표를 취소하는 경우
유저가 이미 찬성 투표를 한 상태이기 때문에 findOne을 호출하면 반환 값이 const poll = { selectprefer: '7' };
이어야 한다.
const poll = { selectprefer: '7' };
jest.spyOn(prefersRepository, 'findOne').mockResolvedValue(poll);
그리고 if문을 통과하고 createQueryBuilder
를 호출 하게 되면 가짜 QueryBuilder를 반환한다.
jest.spyOn(prefersRepository, 'createQueryBuilder').mockReturnValue({
delete: deleteMock,
from: jest.fn().mockReturnThis(),
where: jest.fn().mockReturnThis(),
select: jest.fn().mockReturnThis(),
execute: jest.fn().mockResolvedValue(undefined),
getRawOne: jest.fn().mockResolvedValue(undefined),
});
mockReturnValue
를 사용하면 Mock 함수는 항상 동일한 값을 반환한다.
마지막으로, toHaveBeenCalled();
를 통해서 deleteMock
메서드가 호출 되었는지 여부를 체크한다.
투표에 반대한 유저가 반대표를 취소하는 경우 [ 같은 경우이므로 생략 ]
투표를 하지 않았다면 투표를 하고 결과를 보는경우
findOne 메서드까지는 동일한 부분이니 설명 생략
jest.spyOn(prefersRepository, 'save').mockResolvedValue(undefined);
는 undefined를 반환하게 한다.
저장을 한 후에 데이터를 가져와야 한다. 여기서 mockImplementationOnce
를 사용하면 Mock 함수는 처음 호출될 때만 특정 함수의 구현을 따르고 이후 호출에서는 원래의 반환 값을 사용하는 차이가 있다. 상황에 맞지는 않지만 사용해 보았다.
jest.spyOn(prefersRepository, 'createQueryBuilder').mockImplementation(
() =>
({
where: jest.fn().mockReturnThis(),
select: jest.fn().mockReturnThis(),
getRawOne: jest.fn().mockResolvedValue(count),
} as any),
);
describe('createPostPoll', () => {
it('이미 찬성에 투표한 사람이 반대에 투표하려는 경우', async () => {
const userIdx = 'fd05b208-12c3-4b6c-bd8e-eea8e5e202c9';
const postIdx = 'fd05b208-12c3-4b6c-bd8e-eea8e5e202c9';
const createPollDto = { proInputValue: false, conInputValue: true };
const poll = { selectprefer: '7' };
jest.spyOn(prefersRepository, 'findOne').mockResolvedValue(poll);
const result = await preferService.createPostPoll(
userIdx,
postIdx,
createPollDto,
);
expect(result).toEqual('이미 찬성에 투표 했습니다.');
});
it('투표에 찬성한 유저가 찬성표를 취소하는 경우', async () => {
const userIdx = 'fd05b208-12c3-4b6c-bd8e-eea8e5e202c9';
const postIdx = 'fd05b208-12c3-4b6c-bd8e-eea8e5e202c9';
const createPollDto = { proInputValue: true, conInputValue: false };
const poll = { selectprefer: '7' };
const deleteMock = jest.fn().mockReturnThis();
jest.spyOn(prefersRepository, 'findOne').mockResolvedValue(poll);
jest.spyOn(prefersRepository, 'createQueryBuilder').mockReturnValue({
delete: deleteMock,
from: jest.fn().mockReturnThis(),
where: jest.fn().mockReturnThis(),
select: jest.fn().mockReturnThis(),
execute: jest.fn().mockResolvedValue(undefined),
getRawOne: jest.fn().mockResolvedValue(undefined),
});
await preferService.createPostPoll(userIdx, postIdx, createPollDto);
expect(deleteMock).toHaveBeenCalled();
});
it('투표를 하지 않았다면 투표를 하고 결과를', async () => {
const userIdx = 'fd05b208-12c3-4b6c-bd8e-eea8e5e202c9';
const postIdx = 'fd05b208-12c3-4b6c-bd8e-eea8e5e202c9';
const createPollDto = { proInputValue: true, conInputValue: false };
const count = {
/* mock count result */
};
jest.spyOn(prefersRepository, 'findOne').mockResolvedValue(null);
jest.spyOn(prefersRepository, 'save').mockResolvedValue(undefined);
jest.spyOn(prefersRepository, 'createQueryBuilder').mockImplementation(
() =>
({
where: jest.fn().mockReturnThis(),
select: jest.fn().mockReturnThis(),
getRawOne: jest.fn().mockResolvedValue(count),
} as any),
);
const result = await preferService.createPostPoll(
userIdx,
postIdx,
createPollDto,
);
expect(result).toEqual(count);
});
});