如何在 Typescript Mocha 测试挂钩中保留 "this"

How to preserve "this" within Typescript Mocha test hooks

在下面的示例中,token.test.ts 将测试夹具加载到 beforeEach 中的 this.token,以便在 token.behavior.ts 中的挂钩中重复使用。

// token.test.ts
import { shouldBehaveLikeToken } from './token.behavior';

describe("TokenTest", function () {
  beforeEach('reload token fixture', async function () {
    ({ token: this.token }) = await loadFixture();
  });

  shouldBehaveLikeToken();
  // More behavioral test suites
});
// token.behavior.ts
export function shouldBehaveLikeToken(): void {
  describe('balanceOf', function () {
    it('returns the correct balance', async function() {
      expect(await this.token.balanceOf(ADDRESS).to.equal(2)); // WORKS!
    });

  });

  function balanceOf() {
    return this.token.balanceOf(ADDRESS); // DOES NOT COMPILE WITH THIS FUNCTION!
  }
  
}

无论 this.token 上的嵌套断言有多深,我都可以在 Mocha 挂钩 (describe() / it()) 中访问 this.token 就好了。

但是,如果我创建一个辅助函数,它使用 this.token 使测试在测试套件中更具可组合性,我会得到 'this' implicitly has type 'any' because it does not have a type annotationAn outer value of 'this' is shadowed by this container 的错误。无论它是否是箭头函数,也无论函数在哪里定义,都会发生这种情况。

谁能解释一下这是怎么回事?我如何创建一个辅助函数来使用 beforeEach 块中保留的 this

看起来您的外部函数 balanceOf 要求 this 上下文是 Mocha.Context 的上下文,这仅在 Mocha 测试中可用。您必须指定 balanceOf 函数的 this 类型,然后将函数显式绑定到 Mocha.Context 上下文,如下所示:

export function shouldBehaveLikeToken(): void {
  describe('balanceOf', function () {
    it('returns the correct balance', async function() {
      // It is only within this callback that your `this` context is `Mocha.Context`.
      // The context will not carry over outside of the callback.

      expect(await balanceOf.bind(this)().to.equal(2)); // Bind the function here.
    });
  });

  function balanceOf(this: Mocha.Context) { // explicit `this` type here.
    return this.token.balanceOf(ADDRESS);
  }
}

您的第一个 balanceOf 函数无法正确键入 this 的原因是因为所有函数声明(使用 function 关键字创建的函数)将绑定 window 或默认情况下 global,如果您处于严格模式,则为 undefined。您可以阅读有关函数如何绑定其 this 上下文 here.

的更多信息