4

I'd like to check if a function haveBeenCalledWith() the parameters I need, so I can check if my call is correct, and not necessary call the real methods.

I've tried many solutions. Some that I found (Using Jasmine to spy on a function without an object) and (How to spy a function without root object)

I have a plunker with my attempts that might help http://plnkr.co/edit/xmLCNffTvyD8rp9VcRex

The external library I'm using at the moment is the date-fns.

I created a Pipe in Angular 4, like so:

import { Pipe, PipeTransform } from '@angular/core';
// It works if I import all 'date-fns', but it gives me issues with three shaking, so that's not a proper solution
import * as format from 'date-fns/format'; 

@Pipe({
    name: 'dateFnsFormat'
})
export class DateFnsFormatPipe implements PipeTransform {

    transform(value: any, args?: any): any {
        return format(value, args);
    }

}

So I want to test the call of the format function.

If I test without mocking. It works:

import * as format from 'date-fns/format';

const xmasDay = '2017-12-25 12:30:00';

// Works with real function
it('should transform the date from Y-m-d H:m:s to d/m/Y', () => {
    const dateFnsFormatPipe = new DateFnsFormatPipe();
    expect(dateFnsFormatPipe.transform(xmasDay, 'DD/MM/YYYY')).toBe('25/12/2017');
});


// Works with real function
it('should transform the date from Y-m-d H:m:s to d/m/Y H:m:s', () => {
    const dateFnsFormatPipe = new DateFnsFormatPipe();
    expect(dateFnsFormatPipe.transform(xmasDay, 'DD/MM/YYYY HH:mm:ss')).toBe('25/12/2017 12:30:00');
});

Bellow, I show all my attempts and the following errors:

// #1 Attempt with spyOn(window, 'function');
// @link https://stackoverflow.com/a/9511646/3415716
// Error: Error: format() method does not exist
it('#1 should transform the date from Y-m-d H:m:s to d/m/Y H:m:s', () => {
    spyOn(window, 'format');

    const dateFnsFormatPipe = new DateFnsFormatPipe();
    dateFnsFormatPipe.transform(xmasDay, 'DD/MM/YYYY HH:mm:ss');
    expect(window.format).toHaveBeenCalled();
});

// #1b Attempt with spyOn(global, 'function');
// @link https://stackoverflow.com/a/9511646/3415716
// Error: Error: format() method does not exist
it('#1b should transform the date from Y-m-d H:m:s to d/m/Y H:m:s', () => {
    spyOn(global, 'format');

    const dateFnsFormatPipe = new DateFnsFormatPipe();
    dateFnsFormatPipe.transform(xmasDay, 'DD/MM/YYYY HH:mm:ss');
    expect(global.format).toHaveBeenCalled();
});

// #2 Attempt with jasmine.createSpy().and.callFake(function);
// @link https://stackoverflow.com/a/29922957/3415716
// Error: Expected spy unknown to have been called.
it('#2 should transform the date from Y-m-d H:m:s to d/m/Y H:m:s', () => {
    const test = jasmine.createSpy().and.callFake(format);

    const dateFnsFormatPipe = new DateFnsFormatPipe();
    dateFnsFormatPipe.transform(xmasDay, 'DD/MM/YYYY HH:mm:ss');
    expect(test).toHaveBeenCalled();
});


// #3 Attempt with jasmine.createSpy().and.callFake(function);
// @link https://stackoverflow.com/a/29922957/3415716
// Error: Expected spy testSpy to have been called.
it('#3 should transform the date from Y-m-d H:m:s to d/m/Y H:m:s', () => {
    const mySpy = jasmine.createSpy('testSpy', format).and.callThrough();

    const dateFnsFormatPipe = new DateFnsFormatPipe();
    dateFnsFormatPipe.transform(xmasDay, 'DD/MM/YYYY HH:mm:ss');
    expect(mySpy).toHaveBeenCalled();
});

// #4 Attempt with jasmine.createSpy(global, 'function');
// @link https://groups.google.com/forum/#!searchin/jasmine-js/spy$20function%7Csort:relevance/jasmine-js/a3gNCMMd3UM/6iP8jpfIAQAJ
//  Expected spy global to have been called.
it('#4 should transform the date from Y-m-d H:m:s to d/m/Y H:m:s', () => {
    const mySpy = jasmine.createSpy('global', format);
    const mySpyFormat = jasmine.createSpy('format');

    const dateFnsFormatPipe = new DateFnsFormatPipe();
    dateFnsFormatPipe.transform(xmasDay, 'DD/MM/YYYY HH:mm:ss');
    expect(mySpy).toHaveBeenCalled();
    expect(mySpyFormat).toHaveBeenCalled();
});

PS: The example I'm using is within date-fns, however, I'd like to implement the same idea with different libraries. Also, I don't want to include the main file because of the three shaking that I expect from webpack (read https://github.com/ReactiveX/rxjs/issues/1888).

Leo Caseiro
  • 1,667
  • 1
  • 22
  • 35

1 Answers1

2

if you try something like this...

it('should', () => {
      const dffp = new DateFnsFormatPipe();
      spyOn(DateFnsFormatPipe, 'transform').and.callThrough();
      spyOn(dffp, 'format');

      dateFnsFormatPipe.transform(xmasDay, 'DD/MM/YYYY');

      expect(dffp.format).toHaveBeenCalledWith(xmasDay, 'DD/MM/YYYY');
    })

I've been using this method and it works well. You may need to tweak that a bit to work for you but it should be close

Taylor Belk
  • 162
  • 1
  • 16