Подтвердить что ты не робот

Как я могу заглянуть на свойство геттера с помощью жасмина?

Как я могу отслеживать свойство геттера с помощью жасмина?

var o = { get foo() {}, };

spyOn(o, 'foo').and.returnValue('bar'); // Doesn't work.

Это также не работает AFAICT:

spyOn(Object.getOwnPropertyDescriptor(o, 'foo'), 'get').and.returnValue('bar');
4b9b3361

Ответ 1

Эта функция, похоже, не реализована, но нет причин, почему этого не может быть. (Я открыл запрос и он выполнил в запрос на перенос как spyOnProperty, но не сливается с мастером.)

Жасмин spyOn работает, переписывая метод объекта с помощью новой функции, которая вызывает старую функцию. spyOn(obj, prop) делает что-то вроде этого:

var oldFunc = obj[prop];
obj[prop] = function() {
    doSpyStuff();
    return oldFunc.apply(this, arguments);
}

Этот подход не работает для геттеров и сеттеров, так как нотация в виде скобок будет запускать setter/getter, но он не получит к ней доступа. Ваша попытка использовать getOwnPropertyDescriptor находится на правильном пути, но getOwnPropertyDescriptor просто возвращает новый объект, который описывает свойство getters/seters. Изменение свойства на возвращаемом объекте описания с obj[prop] = function() { ... } не вызывает изменения самого свойства.

Вместо этого вам придется придерживаться принципиально иного подхода к перезаписи функции. Вместо того, чтобы переписывать свойство с помощью функции, вам нужно переопределить свойство, чтобы использовать новый getter:

var oldDescriptor = Object.getOwnPropertyDescriptor(o, 'foo');

// test if this is an accessor property
if(oldDescriptor.get) {
    Object.defineProperty(o, 'foo', {
        set: oldDescriptor.set,
        get: function() {
            doSpyStuff();
            return oldDescriptor.get.apply(this);
        }
    });
}

Код Жасмин для spyOn находится в /src/core/SpyRegistry.js, и, в частности, код, который заменяет метод функцией spy, в настоящее время:

  var spy = j$.createSpy(methodName, obj[methodName]);

  currentSpies().push({
    spy: spy,
    baseObj: obj,
    methodName: methodName,
    originalValue: obj[methodName]
  });

  obj[methodName] = spy;

Как описано выше, это полностью переписывает свойства со шпионскими функциями; в настоящее время он не поддерживает переписывание только set или get свойства accessor с помощью definePrpoerty.

Ответ 2

В феврале 2017 года они объединили PR, добавив эту функцию, и выпустили ее в апреле 2017 года.

чтобы шпионить за геттерами/сеттерами, которые вы используете: const spy = spyOnProperty(myObj, 'myGetterName', 'get'); где myObj - ваш экземпляр, "myGetterName" - это имя того, которое определено в вашем классе как get myGetterName() {}, а третий параметр - это тип get или set.

Вы можете использовать те же утверждения, которые вы уже используете со шпионами, созданными с помощью spyOn.

Итак, вы можете, например:

const spy = spyOnProperty(myObj, 'myGetterName', 'get'); // to stub and return nothing. Just spy and stub.
const spy = spyOnProperty(myObj, 'myGetterName', 'get').and.returnValue(1); // to stub and return 1 or any value as needed.
const spy = spyOnProperty(myObj, 'myGetterName', 'get').and.callThrough(); // Call the real thing.

Здесь строка в исходном коде github, где этот метод доступен, если вы заинтересованы.

https://github.com/jasmine/jasmine/blob/7f8f2b5e7a7af70d7f6b629331eb6fe0a7cb9279/src/core/requireInterface.js#L199

Отвечая на исходный вопрос, с жасмином 2.6.1, вы должны:

var o = { get foo() {} };
spyOnProperty(o, 'foo', 'get').and.returnValue('bar');

Ответ 3

Я принял вдохновение от ответа @apsillers и написал следующий помощник (требуется, чтобы prop настраивался, как указано выше)

let activeSpies = [];
let handlerInstalled = false;

function afterHandler() {
    activeSpies.forEach(({ obj, prop, descriptor }) => Object.defineProperty(obj, prop, descriptor));
    activeSpies = [];
}


export function spyOnGetter(obj, prop) {
    const env = jasmine.getEnv();
    const descriptor = Object.getOwnPropertyDescriptor(obj, prop);
    const spy = jasmine.createSpy(`${prop} spy`);
    const copy = Object.assign({}, descriptor, { get: spy });
    Object.defineProperty(obj, prop, copy);
    activeSpies.push({
        obj,
        prop,
        descriptor,
    });

    if (!handlerInstalled) {
        handlerInstalled = true;
        env.afterEach(() => afterHandler());
    }
    return spy;
}

И его можно использовать так:

import { spyOnGetter } from spyExtra;
it('tests the thing', () => {
    spyOnGetter(myObj, 'myProp').and.returnValue(42);
    expect(myObj.myProp).toBe(42);
});

Надеюсь, это полезно!

Ответ 4

Я думаю, что лучший способ - использовать spyOnProperty. Он ожидает 3 свойства, и вам необходимо передать get или set в качестве третьего свойства.

spyOnProperty(o, 'foo', 'get').and.returnValue('bar');

Ответ 5

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

В качестве обходного пути вы можете заставить ваш getter вызвать другую функцию и вместо этого заглянуть туда.

var o = {
     _foo: function(){
        return 'foo'; 
     }, 
     get foo(){
        return this._foo();
     }
};

spyOn(o, '_foo').and.returnValue('bar'); 

Ответ 6

Вы можете сделать это, если не сможете использовать последний жасмин (2.6.1)

const getSpy = jasmine.createSpy().and.returnValue('bar')
Object.defineProperty(o, 'foo', { get: getSpy });

Документация для defineProperty, здесь