본문 바로가기

웹 프론트엔드

[Cypress] API Mocking 하기

Cypress로 테스트하다 보면, API를 Mocking하여 처리해야할 일이 생긴다.

 

다음과 같은 이유가 있다.

1. public api 를 이용할 때는 할당량이 있는 경우가 있어서, 테스트에 할당량을 낭비하지 않기 위해서

2. private api의 경우에도 서버 비용이 발생하기 때문에

 

Cypress는 공식 문서가 매우 잘 돼있기 때문에, 가급적 공식문서 읽기를 추천한다. 

API Mocking은 특히 intercept 개념을 읽으면 된다.

https://docs.cypress.io/api/commands/intercept

 

intercept | Cypress Documentation

Spy and stub network requests and responses. Tip: We recommend you read the Network Requests guide first. cy.intercept() is the successor to cy.route()

docs.cypress.io

 

 

나에게 주어진 상황은 다음과 같다.

1. 유튜브 API 를 이용 중이다.

2. 검색 키를 누르면, Search를 진행하고, 10개의 data 를 fetch 한다.

3. #search-input-keyword 가 submit 되면, fetch를 실행하여 뷰를 렌더링 하는 구조이다.

4. 10개의 영상 데이터가 정상적으로 화면에 보여지는지 테스트한다.

 

API Mocking에는 intercept 개념이 사용된다.

이는 특정 method, url, query 일 때 spying하거나, reponse를 stubbing(mocking)하는 데 쓰인다.

 

// spying only
cy.intercept(url)
cy.intercept(method, url)
cy.intercept(routeMatcher)

// spying and response stubbing
cy.intercept(url, staticResponse)
cy.intercept(method, url, staticResponse)
cy.intercept(routeMatcher, staticResponse)
cy.intercept(url, routeMatcher, staticResponse)

 

spying만 하기 위해서는 위의 방식으로 사용하고, reponse를 받아야 한다면 밑의 방식을 이용하자.

나 같은 경우는 유튜브 영상 데이터를 reponse로 받아야하기 때문에, 밑의 방식을 이용했다. 

그 중에서 3번째인 방식인 routeMatcher를 이용한 방식으로 테스트했다.

 

어떻게 사용하는지 보자.

 

import { BASE_URL, OPTIONS } from '../../src/js/api/api';

describe('유튜브 App 테스트', () => {
  beforeEach(() => { // 모든 테스트 이전에 실행할 코드
    cy.intercept( 
      {
        url: BASE_URL + '*', // BASE_URL에
        query: { // query가 다음과 같을 때
          part: 'snippet',
          type: 'video',
          maxResults: `${LOAD_VIDEOS_COUNT}`,
          q: '우테코',
        },
      },
      { fixture: 'searchResult.json' } // 이를 reponse 한다.
    );
    cy.visit('http://localhost:8080/');
  });

  it('검색을 하면(enter), 10개의 영상 데이터를 받아와서, 화면에 보여준다.', () => {
    cy.get('#search-modal-button').click();
    cy.get('#search-input-keyword')
      .type('우테코{enter}') // enter를 누르면 submit되고, 위에서 mocking한 데이터를 받아올 것이다.
      .then(() => {
        cy.get('#video-list .video-card.real').should(
          'have.length',
          LOAD_VIDEOS_COUNT
        );

        $$('#video-list .video-item__title').forEach(el =>
          cy.get(el).should('have.text')
        );
      });
  });
 }

 

위 inercept 문을 해석하면 다음과 같다.

url이 BASE_URL이며, query가 다음과 같을 때, 그 api는 fixtures에 있는 searchResult.json 파일을 반환한다.

(fixture는 고정물되어 있는 물체를 말하며, 위의 staticResponse와 상응하는 의미이다.)

 

 

fixtures

 

 

fixtures 폴더 안에 searchResult.json을 넣어두고, json 형식으로 정의해놓았다면, import/export 하지 않아도 해당 값을 reponse 한다.