Numerous Philanthropic Misanthropes

    jasmine-mock-factory
    TypeScript icon, indicating that this package has built-in type declarations

    3.0.0 • Public • Published

    Jasmine Mock Factory

    Build Status Coverage Status

    A Jasmine test util that uses a TypeScript class or an instance of a class to create a mock instance of that class.

    Quick Start

    import { SomeClass } from 'some-library';
    import { MockFactory} from 'jasmine-mock-factory';
     
    it('should pass', () => {
        const mockInstance = MockFactory.create(SomeClass);
     
        /* arrange */
        mockInstance._spy.doSomething._func.and.returnValue('awesome!');
     
        /* act */
        mockInstance.doSomething();  // returns 'awesome!'
     
        /* assert */
        expect(mockInstance.doSomething).toHaveBeenCalled();
    }

    Quick reference

      /* create a mock from a class*/
      const mockInstance1 = MockFactory.create(RealClass);
     
      /* create a mock from an instance*/
      const mockInstance2 = MockFactory.create(realInstance);
     
      /* access a function spy */
      const spy1 = mockInstance._spy.functionName._func
     
      /* access a getter spy */
      const spy2 = mockInstance._spy.propertyName._get
     
      /* access a setter spy */
      const spy3 = mockInstance._spy.propertyName._set

    Prerequisite

    • This util is built with and for Jasmine test framework. Basic understanding of Jasmine is assumed.
    • This util requires ES6 Proxy.

    Usage

    Install

    npm install jasmine-mock-factory --save-dev

    Import

    Import the library with ES6 Module Syntax:

    import { MockFactory } from 'jasmine-mock-factory'

    Creating a mock

    From a TypeScript class

    class RealClass {
      // This is a typescript class
    }
     
    ...
     
    const mockInstance = MockFactory.create(RealClass);

    From an instance of a class

    const realInstance: RealInterface = new RealClass();
     
    ...
     
    const mockInstance = MockFactory.create(realInstance);

    From window objects

    /* make sure you have included dom types from the TypeScript library */
    const mockWindow  = MockFactory.create(window);
    const mockDocument = MockFactory.create(document);
    const mockLocation = MockFactory.create(location);

    Using a mock

    • MockFactory.create() will return an object with the same interface as the real object. You can invoke functions and access properties on this object.
    • In addition, the mock object provides a _spy facade, where you can access and config spies on functions and properties.
      const mockInstance = MockFactory.create(location);
      mockInstance.reload(); // use it as if it were the real window.location
      let temp = mockInstance.search; // use it as if it were the real window.search
      mockInstance.hash = 'myHash'; // use it as if it were the real window.hash
      mockInstance._spy.reload._func; // returns the spy behind location.reload
      mockInstance._spy.search._get; // returns the spy behind the getter for location.search
      mockInstance._spy.hash._set; // returns the spy behind the setter for location.hash

    Invoking functions

    • All functions will have a jasmine.Spy as the initial value. The spy cannot be overwritten and returns undefined by default.
    • To access protected and private functions, cast the mockInstance as any or use bracket notation.
      mockInstance.publicFunction(42); // the spy behind it is invoked with 42
     
      (mockInstance as any).privateFunction(42);
      mockInstance['privateFunction'](42); // equivalent

    Spying/stubbing functions

    • You can change return values of functions or assert their calls by accessing them directly or through the _spy facade.
    • Access a function spy on mockInstance._spy.functionName._func.
      /* stubbing a public function */
      mockInstance._spy.publicFunction._func.and.returnValue(42);
      (mockInstance.publicFunction as jasmine.Spy).and.returnValue(42); // equivalent, but not recommented because it requires casting
     
      /* stubbing a private function */
      mockInstance._spy.privateFunction._func.and.returnValue(42);
      ((mockInstance as any).privateFunction as jasmine.Spy).and.returnValue(42); // equivalent, but not recommented because it requires casting twice

    Accessing properties

    • All properties have undefined as the initial value. The value can be overwritten with anything.
    • You have read and write access to any property, even if they were readonly in the real object.
    • To read or write a protected or private property, cast the mockInstance as any or use bracket notation.
    • To write a readonly property, cast the mockInstance as any. The bracket notation won't work.
    • By default, modification to the properties will persist, even if a getter or setter exists in the real object.
      /* persist modification */
      mockInstance.publicProperty = 42;
      let temp = mockInstance.publicProperty; // temp = 42;
     
      /* access readonly property */
      mockInstance.readonlyProperty = 42; // typescript compiler error
      (mockInstance as any).readonlyProperty = 42; // no problem
      mockInstance['readonlyProperty'] = 42; // typescript compiler error
     
      /* access private property */
      (mockInstance as any).privateProperty = 'foo';
      mockInstance['privateProperty'] = 'foo'; // equivalent

    Spying/stubbing getters and setters

    • All properties have spies on the getter and setter, even if the getter and setter don't exist in the real object.
    • Access a getter spy on mockInstance._spy.propertyName._get.
    • Access a setter spy on mockInstance._spy.propertyName._set.
    • NOTE: modification to the properties will not persist after getter or setter spies are customized
    • NOTE: expect(mockInstance.someProperty).toBe(...) will trigger mockInstance._spy.someProperty._get. Design the sequence of your assertions carefully to avoid shooting yourself in the foot.
      /* assert getter calls */
      let temp = mockInstance.publicProperty;
      expect(mockInstance._spy.publicProperty._get).toHaveBeenCalled();
     
      /* assert setter calls on a public property */
      mockInstance.publicProperty = 42;
      expect(mockInstance._spy.publicProperty._set).toHaveBeenCalledWith(42);
     
      /* customize setter */
      expect(mockInstance.publicProperty).toBe(42); // pass. setter hasn't been customized
      mockInstance._spy.publicProperty._set.and.callFake(() => { /* noop */});
      mockInstance.publicProperty = 100;
      expect(mockInstance.publicProperty).toBe(100); // fail. expect 42 to be 100. setter was customized
     
      /* assert setter calls on a private property */
      mockInstance['privateProperty'] = 42;
      expect(mockInstance._spy.privateProperty._set).toHaveBeenCalledWith(42);
     
      /* customize getter */
      expect(mockInstance['privateProperty']).toBe(42); // pass. getter hasn't been customized
      mockInstance._spy.privateProperty._get.and.returnValue(100);
      mockInstance['privateProperty'] = 42;
      expect(mockInstance['privateProperty']).toBe(42); // fail, expect 100 to be 42. getter was customzied

    Develope

    • npm install to install dev dependencies
    • npm run build to build the library
    • npm run test to test the library

    Install

    npm i jasmine-mock-factory

    DownloadsWeekly Downloads

    160

    Version

    3.0.0

    License

    MIT

    Unpacked Size

    23.2 kB

    Total Files

    9

    Last publish

    Collaborators

    • chuanqisun