Я хочу проверить, что аргумент, переданный функции, является ссылкой на функцию, но ссылка на функцию передается с помощью bind().

Рассмотрим этот код, который должен быть протестирован (сокращен для краткости):

initialize: function () {
    this.register(this.handler.bind(this));
}

И этот модульный тест, чтобы проверить, был ли register() вызван с handler():

it('register handler', function () {
    spyOn(bar, 'register');
    bar.initialize();
    expect(bar.register.calls.argsFor(0)[0]).toEqual(bar.handler);
});

Аргумент не равен ссылке на функцию, которую я предполагаю, из-за связанной функции, используя bind() - как я могу проверить, что передается правильная ссылка на функцию, все еще используя метод bind() для нее?

Примечание: это не относится к жасмину, я просто подумал, что это было уместно из-за используемых методов.

9
Phil Cooper 16 Дек 2015 в 12:09

3 ответа

Лучший ответ

Вместо того

expect(bar.register.calls.argsFor(0)[0]).toEqual(bar.handler);

Ты можешь сделать

expect(Object.create(bar.handler.prototype) instanceof bar.register.calls.argsFor(0)[0])
  .toBe(true);

Или

expect(Object.create(bar.handler.prototype)).
  toEqual(jasmine.any(bar.register.calls.argsFor(0)[0]));

Это работает, потому что внутренний метод [[HasInstance]] связанной функции делегируется методу [[HasInstance]] исходной функции.

Этот пост в блоге содержит более подробный анализ связанных функций.

6
Kos 4 Сен 2017 в 12:18

Мне удалось сохранить тест и код и обойти его.

Я шпионю за ссылкой на функцию с пустым anon func, а затем вызываю ее, когда слежу за методом регистра - если шпион вызывается, я знаю, что ему передана правильная ссылка.

it('register handler', function () {
    spyOn(bar, 'handler').and.callFake(function(){}); // do nothing
    spyOn(bar, 'register').and.callFake(function(fn){
        fn();
        expect(bar.handler).toHaveBeenCalled();
    });
    bar.initialize();
});
1
Phil Cooper 16 Дек 2015 в 12:15

this.handler.bind(this) создает совершенно новую функцию, поэтому она не равна bar.handler. См. Function.prototype.bind ().

Вы можете передать ограниченную функцию в качестве аргумента функции initialize и затем проверить ее, например:

var handler = bar.handler.bind(bar);
bar.initialize(handler);
expect(bar.register.calls.argsFor(0)[0]).toEqual(handler);
1
madox2 16 Дек 2015 в 10:08