In the below example, token.test.ts
loads a test fixture into this.token
within a beforeEach
, to be reused within the hooks in 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!
}
}
Regardless of how deeply nested assertions on this.token
are, I am able to access this.token
within Mocha hooks (describe()
/ it()
) just fine.
However, if I create a helper function that uses this.token
for making tests more composable within the test suite, I get the errors that 'this' implicitly has type 'any' because it does not have a type annotation
and An outer value of 'this' is shadowed by this container
. This happens regardless of whether it is an arrow function or not, and regardless of where the function is defined.
Can someone explain what's going on? How can I make a helper function that uses the preserved this
from the beforeEach
block?
CodePudding user response:
It looks like your external function balanceOf
is requiring the this
context to be that of Mocha.Context
which is only available inside of a Mocha test. You must specify the this
type of your balanceOf
function, then bind the function to the Mocha.Context
context explicitly like so:
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);
}
}
The reason why your first balanceOf
function cannot correctly type this
is because all function declarations (functions created with the function
keyword) will bind either window
or global
by default, or to undefined
if you're in strict mode. You can read more about how functions bind their this
context here.