Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

mocks

vojtajina17.8k0.0.15

Set of mock modules for easy testing (fs, http)

mock, stub, dummy, test double, fake, nodejs, js, testing, test, fs, fs mock, http, http mock

readme

Node Mocks Build Status

Set of mocks and utilities for easier unit testing with Node.js.

See http://howtonode.org/testing-private-state-and-mocking-deps for better explanation.

Prerequisites

Installation

sudo npm install -g mocks

# or install in local folder
npm install mocks

Example

Mocking a file system

// during unit test - we inject mock file system instead of real fs
var fs = require('fs');

// even if this function is not public, we can test it directly
var filterOnlyExistingFiles = function(collection, done) {
  var filtered = [],
      waiting = 0;

  collection.forEach(function(file) {
    waiting++;
    fs.stat(file, function(err, stat) {
      if (!err && stat.isFile()) filtered.push(file);
      waiting--;
      if (!waiting) done(null, filtered);
    });
  });
};
# simple unit test (jasmine syntax, coffescript)
describe 'app', ->
  mocks = require 'mocks'
  loadFile = mocks.loadFile
  app = done = null

  beforeEach ->
    done = jasmine.createSpy 'done'
    # load the file and inject fake fs module
    app = loadFile __dirname + '/app.js',
      fs: mocks.fs.create
        'bin':
          'run.sh': 1,
          'install.sh': 1
        'home':
          'some.js': 1,
          'another.txt': 1
        'one.js': 1,
        'two.js': 1,
        'three.js': 1


  it 'should return only existing files', ->
    done.andCallFake (err, filtered) ->
      expect(err).toBeFalsy()
      expect(filtered).toEqual ['/bin/run.sh']

    app.filterOnlyExistingFiles ['/bin/run.sh', '/non.txt'], done
    waitsFor -> done.callCount

  it 'should ignore directories', ->
    done.andCallFake (err, filtered) ->
      expect(filtered).toEqual ['/bin/run.sh', '/home/some.js']

    app.filterOnlyExistingFiles ['/bin/run.sh', '/home', '/home/some.js'], done
    waitsFor -> done.callCount

Faking randomness

Non-blocking I/O operations can return in random order. Let's say you read a content of two files (asynchronously). There is no guarantee, that you get the content in right order. That's fine, but we want to test our code, whether it can handle such a situation and still work properly. In that case, you can use predictableNextTick, which process callbacks depending on given pattern.


  it 'should preserve order', ->
    done.andCallFake (err, filtered) ->
      expect(filtered).toEqual ['/one.js', '/two.js', '/three.js']

    app.filterOnlyExistingFiles ['/one.js', '/two.js', '/three.js'], done
    waitsFor -> done.callCount

This test will always pass. That's cool, as we like to see tests passing. The bad thing is, that it does not work in production, with real file system, as it might return in different order... So, we need to test, whether our app works even when the fs returns in random order. Having randomness in unit tests is not good habit, as it leads to flaky tests. Let's change the previous unit test to this:

  it 'should preserve order', ->
    done.andCallFake (err, filtered) ->
      expect(filtered).toEqual ['/one.js', '/two.js', '/three.js']

    mocks.predictableNextTick.pattern = [2, 0, 1]
    app.filterOnlyExistingFiles ['/one.js', '/two.js', '/three.js'], done
    waitsFor -> done.callCount

Now, the unit test fails, because our fake file system calls back in different order. Note, it's not random, as you explicitly specified the pattern (2, 0, 1), so it the fake fs will consistently call back in this order: /three.js, /one.js, two.js.

API

Currently supported API is only very small part of real Node's API. Basically I only implemented methods I need for testing Testacular.

I will keep adding more and of course if anyone wants to help - pull requests are more than welcomed.

fs

  • stat(path, callback)
  • readdir(path, callback)
  • readFile(path [, encoding], callback)
  • readFileSync(path)
  • watchFile(path [, options], callback)
  • _touchFile(path, mtime, content) *

http

  • http.ServerResponse
  • http.ServerRequest

glob

loadFile(path [, mocks] [, globals])

predictableNextTick(fn)

predictableNextTick.pattern

changelog

v0.0.15

  • feat(fs): support relative paths
  • fix(util.loadFile): do not override the exceptions

v0.0.14

  • http.ServerResponse: publish headerSent, getHeader, write
  • http.ServerRequest: add getHeader

v0.0.13

  • Add http.ServerRequest.headers

v0.0.12

  • http.ServerResponse emit "end" event

v0.0.11

  • Added exists/existsSync to fs mocks

v0.0.10

  • Make http.ServerResponse and http.ServerRequest event emitters

v0.0.9

  • Normalize path separator

v0.0.8

  • Add fs.mkdirSync()
  • Add fs.readdirSync()

v0.0.7

  • Allow injecting mocks into nested deps

v0.0.6

  • Add fs.mkdir()
  • Add fs.statSync()
  • Add fs.writeFile()

v0.0.5

  • Trivial implementation of chokidar
  • Trivial mock for node-glob
  • Improve predictableNextTick to follow pattern even for nested callbacks

v0.0.4

Set error code on exceptions

v0.0.3

  • Correct stack trace when syntax error during loadFile
  • Add missing globals to util.loadFile

v0.0.2

  • Update loadFile - allow passing globals

v0.0.1

  • Initial version, extracted from SlimJim