[TIL] supertest로 integration test하기

김시원·2023년 5월 10일
0

TIL

목록 보기
19/50
post-custom-banner

📌 Issues encountered

Issue #1

supertest로 로그인, auth-middleware 검증하기

Issue #2

수정, 삭제 권한이 없는 error test case 만들기

Issue #3

이슈 1과 2에 관련된 리팩토링

📌 What I tried

Issue #1

1) userData를 담는 객체를 정의한다.
2) login API test

  test("POST /api/auth/login API (login) Integration Test", async () => {
    const loginRequestBodyParams = {
      nickname: userData.nickname,
      password: userData.password,
    };
    const response = await supertest(app)
      .post(`/api/auth/login`) // API의 HTTP Method & URL
      .send(loginRequestBodyParams); // Request Body

    /** POST /api/auth/login API의 검증 로직 **/
    // 1. API를 호출하였을 때, 로그인이 성공적으로 실행할 경우 200 Http Status Code를 반환한다.
    expect(response.status).toEqual(200);
    // 2. API 호출이 완료되면, Authorization과 refreshtoken 값을 body 데이터로 전달한다.
    userData.accessToken = response.body.Authorization;
    userData.refreshToken = response.body.refreshtoken;
  });

login API test에서 userData 객체에 access token과 refresh token을 저장한다
3) auth-middleware mocking하기

test("POST /api/worldcup API (createWorldcup) Integration Test Error Case, Invalid Params Error", async () => {
    const createWorldcupRequestBodyParamsByInvalidParamsError = {
      title: "Title_InvalidParamsError",
      content: "Content_InvalidParamsError",
    };

    const response = await supertest(app)
      .post(`/api/worldcup`) // API의 HTTP Method & URL
      .set("Authorization", `Bearer ${userData.accessToken}`) // 헤더에 Access Token 세팅
      .set("refreshtoken", `${userData.refreshToken}`) // 헤더에 Refresh Token 세팅
.send(createWorldcupRequestBodyParamsByInvalidParamsError); // Request Body

    /** POST /api/worldcup API의 에러 케이스 검증 로직 **/
    // 1. API를 호출하였을 때, InvalidParamsError가 발생하여 412 Http Status Code를 반환합니다.
    expect(response.status).toEqual(412);
    // 2. API의 Response는 { errorMessage: '"choices" is required' }의 형식을 가집니다
    expect(response.body).toMatchObject({
      errorMessage: '"choices" is required',
    });
  });
  • set() 함수를 사용해서 header에 담을 데이터를 설정할 수 있다. 토큰 정보들은 login시, 다음과 같이 header에 담기기 때문에
res.status(200).json({
        Authorization: `${userData.accessObject.type} ${userData.accessObject.token}`,
        refreshtoken: userData.refreshToken,
      });

   auth-middleware에서 두 토큰들을 header에서 가져오는 동작을 mocking하였다.

Issue #2

1) 다른 유저로 회원가입, 로그인을 진행하였다.
2) 처음에 user1으로 delete까지 했더니, 비교할 worldcup post 데이터가 없어서 user1이 월드컵을 2개 생성하는 것으로 로직을 변경하였다.
3) 근데, 더 좋은 방법이 없을까?

Issue #3

1) supertest에는 agent라는 가상의 사용자를 둘 수 있다!
2) 특히, 내가 agent 없이 통합 테스트를 했을 때 auth-middleware를 처리하는 부분에서 막혔었는데, supertest는 브라우저가 쿠키 값을 기본으로 보내는 것처럼 비슷한 행동을 할 수 있는 메서드인 agent()를 제공한다.
3) 즉, agent()는 요청을 지속하여 로그인 상태를 유지할 수 있다!
4) agent() 사용법은 다음과 같다.

describe('POST /api/auth/login', () => {
	const agent = request.agent(app);
	beforeEach((done) => {
		agent.post('/api/auth/login')
			 .send({
				 nickname: userData.nickname,
			      password: userData.password,
			      email: userData.email,
			 })
			 .end(done);
	});

	test("POST /api/worldcup", async () => {
	    const createWorldcupRequestBodyParams = {
	      title: worldcupData2.title,
	      content: worldcupData2.content,
	      choices: worldcupData2.choices,
	    };
	    const response = await agent
	      .post(`/api/worldcup`)
	      .send(createWorldcupRequestBodyParams);
		
		expect(response.status).toEqual(201)
		expect(response.body).toMatchObject({
		      newWorldcup: {
		        worldcup_id: worldcupData2.worldcup_id,
		        user_id: userData.user_id,
		        title: createWorldcupRequestBodyParams.title,
		        content: createWorldcupRequestBodyParams.content,
		        choices: createWorldcupRequestBodyParams.choices,
		      },
		    });
	  });
});

📌 What I newly learned

  • supertest로 integration test하기
  • TDD
  • nodemailer
  • 디자인 패턴 - 생성 패턴

📌 What to learn next

  • CI/CD
  • 트러블 슈팅 발표 파트 정리
  • 스토리텔링 발표 정리
post-custom-banner

0개의 댓글