JS

  • Array(5).map(...)으로는 5개의 값을 얻지 못한다! Array(5).fill(0).map(...)와 같이 값이 채워져있어야 한다.

Jest

  • 슬슬 Controller도 테스트를 추가하니까, 얘네가 Repository 테스트와 겹치면서 같은 Collection을 사용하니까 테스트가 또 꼬이기 시작한다. 그래서 예전에 고려했던 --runInBand를 다시 고려하려고 정보를 좀 찾아보았다.
  • 찾아보니 --runInBand 플래그를 주는게 어쩌면 더 좋을 수도 있겠다. 어떤 stackoverflow의 질문 글을 보면, 오히려 속도가 증가하는 경우도 있다고 한다. 또 이를 CI 파이프라인에 아예 플래그로 넣어줬다고 한다. 나도 그냥 넣어야겠다.

Faker

  • Faker.js (우리혁 아님)
    테스트 할 때마다 테스트 데이터 만들기 귀찮으니까, faker를 이용해서 Faker객체들을 만들었다. 예를 들면 아래와 같은 형식이다.
import faker from 'faker'
import IRestaurantVO from '../../domain/restaurant/IRestaurantVO'

export default class RestaurantFaker implements IRestaurantVO {
  readonly categories: string[]
  readonly desc: string
  readonly id: string
  readonly name: string
  readonly rating: number
  readonly slug: string
  readonly thumbnailSrc: string

  [index: string]: string | number | string[]

  constructor() {
    this.id = faker.random.uuid()
    this.slug = faker.lorem.slug()
    this.name = faker.company.companyName()
    this.rating = faker.random.number(5)
    this.thumbnailSrc = faker.internet.url()
    this.categories = Array(faker.random.number({ min: 1, max: 5 }))
      .fill(0)
      .map(() => faker.lorem.word())
    this.desc = faker.lorem.paragraph()
  }
}

앞으로 새로운 VO인터페이스를 정의하면, Faker객체도 만들어주면 된다.

삽질의 추억

Jest & Supertest & Mongoose

첫번째 삽질

테스트가 실행되지 않았다. 자꾸 jest에서 Async timeout 에러가 발생했다. 이유인 즉슨

  • Router를 테스트했다. RouterController함수를 받는다.
  • Controller함수는 AppService를 호출하고, AppServiceRepository를 사용하는데 Repositorymongoose.model을 사용한다.
  • 그런데, mongoose.connect를 테스트 코드에서 사용하지 않았다.
  • 즉, connect를 하지도 않은 상태에서 Repositorymongoose.model로 쿼리를 날리니까 접속 자체가 안되어서 자꾸 타임아웃 에러가 발생한 것이었다.
  • mongoose.connect 로직을 때려박자마자 바로 해결됨...

두번째 삽질

테스트가 실행은 되는데, 자꾸 종료가 되지 않는다. 구글링을 열심히 해봤는데, 나같은 멍청이사람들이 여럿 있었다. 해결하고 난 뒤 이유인 즉슨

  • 이번엔 mongoose.disconnect를 하지 않았다.
  • 그러니까 안끝난다.

세번째 삽질

좋아쓰. mongoose.disconnect도 호출하게 했다. 그래도 안끝나??????????? 해결하고 난 뒤 이유인 즉슨

import mongoose, { ConnectionOptions } from 'mongoose'

const url = 'mongodb://127.0.0.1/yummy'

export const options: ConnectionOptions = {
  useNewUrlParser: true,
  useFindAndModify: false,
  useUnifiedTopology: true,
}

mongoose.connect(url, options).catch(err => {
  console.error(err)
})

나의 멍청한 코드는 이렇게 되어있었다. 나의 더 멍청한 테스트 코드에서는

import { options } from './mongoose'

// ... code ...

이렇게 되어있었는데, 문제점이 보이는가?

그렇다. optionsimport하면서, mongoose.connect가 사이드 이펙트로 실행이 되는 것이다! 고로 mongoose 연결이 두번이나 된 것이다. import에서 한번, 테스트 코드 내에서 한번... 그러니까 안끝나지... 하...

총평

어쨌든, 결국 해결했다. 거의 3시간 동안은

구글링 -> 코드 복붙 -> 아 왜 안되냐? -> 지워봐 -> 다시 복붙 -> 아 왜 안되냐고 나는? -> 다른 코드 보자 -> 복붙 -> 아 왜 안되냐고? 의 무한 반복이었다.

스택오버플로우나 깃헙 이슈를 보긴 했는데, 답변이 많이 달려있기도 하고 깃헙 이슈같은 경우엔 너무 길어서 자세히 보지 않았다. 거의 3시간동안 의미 없는 코드 복붙, 왜 안됨? 개빡치네의 멍청한 루프를 돌다가 이래선 안되겠다 싶어서 깃헙 이슈를 처음부터 쭉 정독했더니 mongoose가 방해하고 있었다는 글을 보게 되어서 바로 해결하였다....................................

교훈: 글을 읽자.