PreferService Jest (2)

이건선·2023년 5월 16일
0

해결

목록 보기
37/48
post-custom-banner

사용할 예제 Service

/**
   *
   * 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 메서드에서 시도해 볼 만한 유닛테스트를 연습해보자.

  1. 이미 찬성에 투표했는데 반대에 투표하는 경우
  2. 이미 반대에 투표했는데 찬에 투표하는 경우
  3. 투표에 반대표를 던진 유저가 반대표를 취소하는 경우
  4. 투표에 찬성표를 던진 유저가 찬성표를 취소하는 경우
  5. 투표를 하지 않았다면 투표를 하고 결과를 보는경우

생각 해볼만한 테스트

  • 이미 찬성에 투표했는데 반대에 투표하는 경우

    1. 유저가 이미 찬성 투표를 한 상태이기 때문에 findOne을 호출하면 반환 값이 const poll = { selectprefer: '7' }; 이어야 한다.

      jest.spyOn(prefersRepository, 'findOne').mockResolvedValue(poll);
    2. 유저는 이미 찬성을 한 상태이지만 모종의 이유로 반대에 투표하고 싶어하는 상황이므로 const createPollDto = { proInputValue: false, conInputValue: true }; 로 conInputValue가 true인 상황이다.

    3. 그러므로 result의 값은 toEqual의 message 값과 일치할 것이다.

      expect(result).toEqual('이미 찬성에 투표 했습니다.');
  • 이미 반대에 투표했는데 찬성에 투표하는 경우 [ 같은 경우이므로 생략 ]

  • 투표에 찬성한 유저가 찬성표를 취소하는 경우

    1. 유저가 이미 찬성 투표를 한 상태이기 때문에 findOne을 호출하면 반환 값이 const poll = { selectprefer: '7' }; 이어야 한다.

      const poll = { selectprefer: '7' };
      
            jest.spyOn(prefersRepository, 'findOne').mockResolvedValue(poll);
    2. 그리고 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),
            });
    3. mockReturnValue를 사용하면 Mock 함수는 항상 동일한 값을 반환한다.

    4. 마지막으로, toHaveBeenCalled(); 를 통해서 deleteMock 메서드가 호출 되었는지 여부를 체크한다.

  • 투표에 반대한 유저가 반대표를 취소하는 경우 [ 같은 경우이므로 생략 ]

  • 투표를 하지 않았다면 투표를 하고 결과를 보는경우

    1. findOne 메서드까지는 동일한 부분이니 설명 생략

    2. jest.spyOn(prefersRepository, 'save').mockResolvedValue(undefined); 는 undefined를 반환하게 한다.

    3. 저장을 한 후에 데이터를 가져와야 한다. 여기서 mockImplementationOnce를 사용하면 Mock 함수는 처음 호출될 때만 특정 함수의 구현을 따르고 이후 호출에서는 원래의 반환 값을 사용하는 차이가 있다. 상황에 맞지는 않지만 사용해 보았다.

      jest.spyOn(prefersRepository, 'createQueryBuilder').mockImplementation(
              () =>
                ({
                  where: jest.fn().mockReturnThis(),
                  select: jest.fn().mockReturnThis(),
                  getRawOne: jest.fn().mockResolvedValue(count),
                } as any),
            ); 

createPostPoll 메서드 테스트코드

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);
    });
  });

커버리지 확인

profile
멋지게 기록하자
post-custom-banner

0개의 댓글