监视没有对象的函数

时间:2017-04-26 16:24:37

标签: javascript unit-testing angular typescript jasmine

我正在测试pub子类的发布方法。我在beforeEach函数中创建一个回调函数并订阅该类。在it方法中,我发布事件并尝试测试回调被调用,这基本上是类的工作方式。我已经让测试工作并且它通过但问题是我必须使用setTimeout才能使其工作。我相信这可能不是正确的方法。

describe('publish', () => {
  let testpublish;
  let callback;

  beforeEach(() => {
    callback = function(data) { return data + 10; }
    testpublish = {
      'id': 'testpublish1',
      'event': 'testpublish',
      'callback': callback
    };
    subject.subscribe(testpublish);
  });

  it('should call the subscription function', () => {
    subject.publish('testpublish', 9);
    setTimeout(() => {
      expect(callback).toEqual(19);
    });
  });
});

我最初想监视回调只是为了看它是否被调用但是Jasmine的文档说我必须将我的方法放在一个对象中:

spyOn(obj,methodName)→{Spy}

任何有关更好方法的建议都将受到赞赏。感谢。

PubSub类如果有用吗?

@Injectable()
export class Pubsub {
  private events: any = {};

  public subscribe(config: any) {
    let event = config['event'];
    this.events[event] = this.events[event] || [];

    if (this.events[event].length < 1) {
      this.events[event].push(config);
    } else {
      for (let i = 0; i < this.events[event].length; i++) {
        if (this.events[event][i].id !== config.id) {
          this.events[event].push(config);
        }
      }
    }
  }

  public unsubscribe(obj: Object) {
    let event = obj['event'];
    let id = obj['id'];

    if (this.events[event]) {
      this.events[event] = this.events[event].filter((eventObj) => {
        return eventObj.id !== id;
      });
    }

    if (this.events[event].length === 0) {
      delete this.events[event];
    }
  }

  public publish(event: string, data: any) {
    if (this.events[event]) {
      this.events[event].forEach(function(obj) {
        obj.callback(data);
      });
    }
  }

  public getEvents() {
    return this.events;
  }
}

2 个答案:

答案 0 :(得分:0)

现有函数不能被监视,因为间谍是一个新函数,并且对原始函数的引用已经在被调用的地方使用。

考虑到callback函数是在测试本身中定义的,而不是在应用程序内部,它应该首先被定义为间谍:

callback = jasmine.createSpy();

它甚至不必做某事,因为它的返回值不会为测试增加价值。

它的测试类似于

const arg = {};
subject.publish('testpublish', arg);

expect(callback.calls.count()).toBe(1);
expect(callback.calls.first().args[0]).toBe(arg);

publish是同步的,同时也是同类的其余部分。这里不需要setTimeout,这在这里是有害的。如果没有为测试指定done参数,则会将其视为同步参数,setTimeout会在此测试中忽略断言。

  it('should pass', () => {
    setTimeout(() => {
      expect(1).toBe(2);
    });
  });

将永远通过。并且只有当套件没有其他测试时,才会触发SPEC HAS NO EXPECTATIONS警告。

答案 1 :(得分:0)

jasmine.createSpy(&#39; spy&#39;)会奏效。

 describe('publish', () => {
  let testpublish;
  let callback;
  let subject = new Pubsub();

  beforeEach(() => {

    callback = function (data) {
      return data + 10;
    }
    testpublish = {
      'id': 'testpublish1',
      'event': 'testpublish',
      'callback': jasmine.createSpy('spy')
    };
    subject.subscribe(testpublish);
  });

  it('should call the subscription function', () => {
    subject.publish('testpublish', 9);
    expect(testpublish.callback).toHaveBeenCalledWith(9);
  });
});