您如何模拟和扩展外部定义的类及其原型?

时间:2019-07-09 11:02:25

标签: typescript unit-testing mocking mocha screeps

背景故事

我正在玩一个名为screeps的游戏,该游戏可让您编写在游戏中执行操作的bot / ai。完成此操作的方法是上传在具有可用常量,类和定义的环境中运行的代码。

这些定义是通过以下程序包定义的 https://www.npmjs.com/package/@types/screeps

现在,我正在使用打字稿编写代码,并使用汇总功能将其编译为爬行,我正在使用以下入门包 https://github.com/screepers/screeps-typescript-starter

我正在尝试使用以下框架进行模拟 https://www.npmjs.com/package/@fluffy-spoon/substitute

问题

在mocha中运行时,我必须从游戏中对环境的功能进行存根/模拟,而在测试框架中运行时则不存在。 我设法模拟了常量,并在其他人的帮助下使它们在Mocha中运行。但现在我坚持为对象Creep

扩展原型

prototypes.ts

Object.defineProperty(Creep.prototype, "task", {
      get() {
        ... logic
      },
      set(task: ITask | null) {
        ... logic
      }
    })

测试

import "../constants"
import "../../src/tasks/prototypes"
import { Task } from "tasks/Task"
import { Game, Memory } from "./mock"
import { assert } from "chai"
import { Substitute, Arg } from "@fluffy-spoon/substitute"

describe("tasks", () => {
  before(() => {
    // runs before all test in this block
  })

  beforeEach(() => {
    // runs before each test in this block
    // @ts-ignore : allow adding Game to global
    global.Game = _.clone(Game) as Game
    // @ts-ignore : allow adding Memory to global
    global.Memory = _.clone(Memory)
  })

  it("Creep should have extended prototyped", () => {
    const testCreep = Substitute.for<Creep>()

    const task = testCreep.task

    assert.isNotNull(task)

  })
})

我运行测试时出现以下错误

  

... \ dist \ test-unit.bundle.js:3324
  }(chai));
  ^
  ReferenceError:未定义蠕变

这是有道理的,因为游戏引擎或测试环境尚未定义蠕变类,因此导入prototypes.ts无法对其进行扩展 但是我不确定如何使它真正起作用。

1 个答案:

答案 0 :(得分:0)

通过按照常量定义中的方法做一些事情,我设法使其运行起来

mock.ts

import { Substitute, Arg } from "@fluffy-spoon/substitute"

export const Game = Substitute.for<Game>()

const mockScreeps = () => {
  const g = global as any

  g.Game = Game
  g.Creep = (function() {
    function Creep() {}

    return Creep
  })()

  g.RoomObject = (function() {
    function RoomObject() {}

    return RoomObject
  })()

  g.RoomPosition = (function() {
    function RoomObject() {}

    return RoomObject
  })()
}

mockScreeps()

测试

import "../constants"
import { Memory } from "./mock"
import { assert } from "chai"
import "../../src/tasks/prototypes"

describe("tasks", () => {
  before(() => {
    // runs before all test in this block
  })

  beforeEach(() => {
    // runs before each test in this block
    // @ts-ignore : allow adding Memory to global
    global.Memory = _.clone(Memory)
  })

  it("Creep should have extended prototyped", () => {
    const creep = new Creep("test")
    creep.memory = {
      task: {
        tick: 123,
        name: "dummy"
      }
    }

    const task = creep.task
    assert.isNotNull(task)
    if (task && creep.memory.task) {
      assert.isString(task.memory.name)
      assert.equal(task.memory.name, creep.memory.task.name)
    }

  })
})

它现在可以运行我的测试,在使用尚未被模拟的东西进行测试时,我只需要扩展模拟即可。