首页 > 解决方案 > 如何监视内部具有 Promise 且不返回结果但处理响应本身的函数?

问题描述

我怎样才能 spyOn 一个名为放置在对象中的方法?

// Game.js

export default {
    mine: null,

    handle: function(me) {
        console.log("   FOOOOO " + me)
    },

    setSource: function() {
        this.mine.getSource().then((response) => {
          const {source} = response
          this.handle(source)
        })
    }
}

在这里我尝试窥探:

// GameSpec.js

import Game from '../../lib/jasmine_examples/Game'

Game.mine = {}

describe("Game", function() {
  it("should set source and handle it", function() {

    Game.mine.getSource = () => {
      return new Promise((resolve)=>{
        resolve( {
          source : 'BAAAAR'
        })
      })
    }

    spyOn(Game, 'handle').and.callThrough()

    Game.setSource()

    expect(Game.handle).toHaveBeenCalled()
  });
});

在输出中,您可以看到函数“handle”被调用:

Started
F   FOOOOO BAAAAR


Failures:
1) Game should set source and handle it
  Message:
    Expected spy handle to have been called.
  Stack:
    Error: Expected spy handle to have been called.
        at <Jasmine>
        at UserContext.<anonymous> (/Users/silverbook/Sites/zTest/jasmine/spec/jasmine_examples/PlayerSpec.js:20:29)
        at <Jasmine>

1 spec, 1 failure

jasmine说它没有被调用。

如果我删除了模拟Promise测试通过,但我需要那里。在另一个测试中,我将在 Promise 中返回一个错误,并让它从另一个函数处理。

所以Promise打破了测试,但为什么呢?

标签: jasminees6-modules

解决方案


测试同步执行,并且在expect排队的回调this.mine.getSource().then()有机会执行之前失败。

对于Jasmine>= 2.7 和async函数支持,您可以将测试函数转换为async函数并添加await Promise.resolve();要暂停同步测试并让任何排队回调执行的位置。

对于您的测试,它看起来像这样:

import Game from '../../lib/jasmine_examples/Game'

Game.mine = {}

describe("Game", function() {
  it("should set source and handle it", async () => {

    Game.mine.getSource = () => {
      return new Promise((resolve)=>{
        resolve( {
          source : 'BAAAAR'
        })
      })
    }
    spyOn(Game, 'handle').and.callThrough();

    Game.setSource();

    await Promise.resolve(); // let the event loop cycle

    expect(Game.handle).toHaveBeenCalled();
  });
});

对于较旧的 (>= 2.0)Jasmine版本,您可以done()像这样使用:

import Game from '../../lib/jasmine_examples/Game'

Game.mine = {}

describe("Game", function() {
  it("should set source and handle it", (done) => {

    Game.mine.getSource = () => {
      return new Promise((resolve)=>{
        resolve( {
          source : 'BAAAAR'
        })
      })
    }
    spyOn(Game, 'handle').and.callThrough();

    Game.setSource();

    Promise.resolve().then(() => {
      expect(Game.handle).toHaveBeenCalled();
      done();
    });

  });
});

推荐阅读