Wondering what’s next for npm?Check out our public roadmap! »

    fake-promise
    TypeScript icon, indicating that this package has built-in type declarations

    2.5.44 • Public • Published

    FakePromise 🙏

    Current Version Build Status Dependencies DevDependencies

    Total control over WHEN ES6 promises are resolved or rejected.

    Why would I want it?

    • FakePromise is a single-class library without any run-time dependencies,
    • It provides a fully functional implementation of Promise with additional testing utilities,
    • Fine grained control of resolution of each promise in a chain (.then(...).then(...)),
    • Thoroughly unit-tested and field-tested in several commercial projects,
    • Usable in modern JavaScript, TypeScript and CoffeeScript.

    This package is intended for use in unit tests. For production, please use Bluebird.

    Installation

    npm install --save-dev fake-promise

    Loading

    // node-style require
    const { FakePromise } = require('fake-promise');
    
    // es6-style default import
    import FakePromise from 'fake-promise';

    Documentation

    For full documentation, please see JSDoc comments in FakePromise class.

    /**
     * TL; DR
     */
    export class FakePromise<T> implements Promise<T> {
      // create already resolved/rejected instances of FakePromise (will resolve whole chain)
      static resolve<U = void>(result ?: U | Promise<U>) : FakePromise<U>;
      static reject<U = void>(error : any) : FakePromise<U>;
    
      // no-arg constructor (without required executor as in standard promise)
      constructor() {}
    
      // promise specification methods (standard ES promise interface)
      then<U>(onresolved : Callback<U>, onrejected ?: Callback<any>) : Promise<U>;
      catch(onrejected : Callback<any>) : Promise<any>;
      finally(onfulfilled : Callback<void>) : Promise<void>;
    
      // resolve/reject full promise chain
      resolve(result ?: T | Promise<T>) : void;
      reject(error ?: any) : void;
    
      // resolve/reject single promise in a chain and return next promise from the chain
      resolveOne<U = void>(result ?: T | Promise<T>) : FakePromise<U>;
      rejectOne<U = void>(error ?: any) : FakePromise<U>;
    
      // set result/error of a promise without resolving/rejecting
      // (to call resolve without arguments afterwards)
      setResult(result : T | Promise<T>) : void;
      setError(error : any) : void;
    }

    (Not So) Minimal Example

    import FakePromise from 'fake-promise';
    
    /**
     * Async function to be tested.
     *
     * It calls `asyncFunctionDependency`, waits for it's promise
     * to be resolved, and returns the result of resolved promise.
     */
    async function testedFunction(asyncFunctionDependency) {
      try {
        const result = await asyncFunctionDependency();
        return result;
      } catch (e) {
        throw e;
      }
    }
    
    /**
     * Tests of `testedFunction` using FakePromise.
     */
    describe('testedFunction(asyncDependency)', () => {
      let dependencyPromise;
      let asyncDependency;
      let resultPromise;
    
      beforeEach(() => {
        // program `asyncDependency` to return a fresh instance of FakePromise
        dependencyPromise = new FakePromise();
        asyncDependency = sinon.stub().returns(dependencyPromise);
    
        resultPromise = testedFunction(asyncDependency);
    
        // At this point `dependencyPromise` is not yet resolved,
        // so `resultPromise` isn't also.
      });
    
      describe('when after resolving dependency promise', () => {
        const expectedResult = "result";
    
        beforeEach(end => {
          // could be also .resolveOne
          dependencyPromise.resolve(expectedResult);
    
          // At this point `dependencyPromise` is resolved, `resultPromise` is not.
          // `setImmediate` is needed in order to wait single tick
          // for resolution of implicit promise created by `await` keyword.
          // `resultPromise` will be resolved before `end` is called.
          setImmediate(end);
        });
    
        it('resolves result promise', () => {
          // Returning promise so that the test will fail if promise is rejected.
          return resultPromise.then(result => result.should.eql(expectedResult));
        });
      });
    
      describe('when after rejecting dependency promise', () => {
        const expectedError = new Error("fail");
    
        beforeEach(end => {
          // could be also .rejectOne
          dependencyPromise.reject(expectedError);
    
          // At this point `dependencyPromise` is rejected, `resultPromise` is not.
          // `setImmediate` is needed in order to wait single tick
          // for rejection of implicit promise created by `await` keyword.
          // `resultPromise` will be rejected before `end` is called.
          setImmediate(end);
        });
    
        it('rejects result promise', () => {
          // Testing rejection is tricky as both resolution and rejection cases
          // must be tested in callbacks of the same promise instance
          // (in single call to `.then(onResolved, onRejected)`).
          return resultPromise.then(
            result => { throw new Error(`expected rejection, got result: ${result}`) },
            err => err.should.eql(expectedError),
          );
        });
      });
    });

    Debugging Techniques

    Printing Stack Traces

    FakePromise stores stack traces of all promise specifications, result provisions and promise resolutions. When debugging problems with tests, it may be helpful to console.log one or more of stored traces.

    // print stack trace of call to `.then(...)` or `.catch`
    console.log(fakePromise.specifyTrace);
    
    // print stack trace of call to `.resove(...)`
    console.log(fakePromise.resolveTrace);
    
    // print stack trace of call to `.reject(...)`
    console.log(fakePromise.rejectTrace);
    
    // print stack trace of calls to `.setResult(...)`
    console.log(fakePromise.resultTrace);
    
    // print stack trace of calls to `.setResult(Promise)`
    console.log(fakePromise.promiseTrace);
    
    // print stack trace of calls to `.setError(...)`
    console.log(fakePromise.errorTrace);

    Using .toString()

    FakePromise implements .toString() method which provides information about internal state of FakePromise instance. When encountering problems with debugging async code, printing used instance of FakePromise may prove helpful.

    console.log(fakePromise);

    License

    Copyright © 2017 - 2019 Maciej Chałapuk. Released under MIT license.

    Install

    npm i fake-promise

    DownloadsWeekly Downloads

    29

    Version

    2.5.44

    License

    MIT

    Unpacked Size

    141 kB

    Total Files

    13

    Last publish

    Collaborators

    • avatar