node file system 테스트하기

mock-fs

개요

gulp의 task들의 test code를 작성하기 위해 고생하였기 때문에 테스트 코드 작성에 많은 도움이 된 mock-fs에 대해 작성하였습니다.

gulp task의 테스트를 위함이였지만, mock-fs의 사용법만을 간단히 알기 위해 del모듈을 테스트한 코드를 작성하였습니다.

mock-fs를 사용하지 않은것과 사용한 것에 대한 코드는 아래와 같습니다.

without mock-fs

아래코드 같이 실제 fs 로 테스트를 진행 한다면 다음과 같은 문제점이 있습니다.

  • 위험성 (테스트 진행중 실제파일에 원치 않은 영향을 줄 수 있다)
  • 느린 테스트 속도
const fs = require('fs')
const del = require('del')
const chai = require('chai')

chai.should()

describe.skip('real fs test', () => {
  beforeEach(() => {
    if(!fs.existsSync('tmp')){
      fs.mkdirSync('tmp')
    }
  })

  it('remove', () => {
    // given
    fs.writeFileSync('tmp/test.txt', 'hello mock fs')

    // when
    del.sync('tmp/test.txt')

    // then
    fs.existsSync('tmp').should.equal(true)
    fs.existsSync('tmp/test.txt').should.equal(false)
  })

  afterEach(() => {
    del('tmp')
  })
})

use mock-fs

다음과 같이 mock-fs를 사용한다면(혹은 비슷한 mock file system) 다음과 같은 장점이 있습니다.

  • 안전성
  • 빠른 테스트 속도
  • 간결해지는 코드
const mock = require('mock-fs')

describe('mock fs test', () => {
  beforeEach(() => {
    mock({
      'tmp': { }
    })
  })

  it('remove', () => {
    // given
    fs.writeFileSync('tmp/test.txt', 'hello mock fs')

    // when
    del.sync('tmp/test.txt')

    // then
    fs.existsSync('tmp').should.equal(true)
    fs.existsSync('tmp/test.txt').should.equal(false)
  })

  afterEach(() => {
    mock.restore()
  })
})

특히 mock-fs는 다음과 같은 강점도 있습니다.

  • mock 함수가 실행되고 나서는 fs모듈은 mock이다.
//test.js
const test2 = require('./test2')

const mock = require('mock-fs')

// 주석 처리를 없애면 실제 파일이 생성되지 않는다.
// mock({ 'tmp': { } })

test2.test() // fs.writeFileSync 내부 실행

//test2.js
const fs = require('fs')

function test(){
    fs.writeFileSync('test.txt', 'hello mock fs')
}

exports.test = test

참고로 mock-fs에서는 process.binding을 이용하여 rebinding 하였습니다.

comments powered by Disqus