如何使用Jasmine和TypeScript监视构造函数

时间:2018-03-13 12:45:53

标签: typescript jasmine mocking spy

有没有办法如何使用Jasmine和Typescript监视构造函数?

有问题的建议解决方案Spying on a constructor using Jasmine不起作用,因为TypeScript does not expose global declarations on window

这是我的用例:

// higher-order function returns validation function with max length
const maxLengthValidator = maxLength => value => value.length > maxLength;

class Book {
  // will be a different function instance each time the Book object is
  // created causing the following test to fail
  nameValidator = maxLengthValidator(42);
  name = null;
  constructor (name) { this.name = name; }
}

class Library {
  persons = [];
  storeBook (book) { this.persons.push(book); }
  createBook (name) { this.storeBook(new Book(name)); }
}

测试失败:

it('createBook passes new book with provided name to storeBook', () => {
  const lib = new Library();
  spyOn(lib, 'storeBook');
  lib.createBook('Start with Why');
  expect(lib.storeBook).toHaveBeenCalledWith(new Book('Start with Why'));
  // Result: Expected spy storeBook to have been called with
  // [ Book({ name: 'Start with Why', nameValidator: Function }) ]
  // but actual calls were
  // [ Book({ name: 'Start with Why', nameValidator: Function }) ]
});

在测试中,我并不关心构造函数的作用。我只需要验证是否已使用正确的参数调用它。这甚至听起来像是模拟的正确用例。

1 个答案:

答案 0 :(得分:0)

可以使用两个函数的toString值对其进行比较。您可以添加自定义的相等性测试器,也可以添加新的匹配器。

添加自定义相等性测试器

function replacer(k, v) {
    if (typeof v === 'function') {
        v = v.toString();
    }
    return v;
}

function stringifyEquality(a, b) {
    try {
        return JSON.stringify(a, replacer) === JSON.stringify(b, replacer) ? true : undefined;
    } catch (e) {
        return undefined
    }
}

beforeAll(() => {
    jasmine.addCustomEqualityTester(stringifyEquality);
});

it('createBook passes new book with provided name to storeBook', () => {
    const lib = new Library();
    spyOn(lib, 'storeBook');
    lib.createBook('Start with Why');
    expect(lib.storeBook.calls.mostRecent().args).toEqual([new Book('Start with Why')]);
});

添加自定义匹配器

function replacer(k, v) {
    if (typeof v === 'function') {
        v = v.toString();
    }
    return v;
}

beforeEach(() => {
    jasmine.addMatchers({
        toBeJsonEqual: function(expected){
            var one = JSON.stringify(this.actual, replacer).replace(/(\\t|\\n)/g,''),
                two = JSON.stringify(expected, replacer).replace(/(\\t|\\n)/g,'');

                return one === two;
            }
    });
});

expect(obj).toBeJsonEqual(obj2);

链接:question 14541287 (pocesar's answer)