Let's say I am using auth0
in typescript in Node.js
I have this class I want to test:
ClassToTest.ts
import { AuthenticationClient, AuthenticationClientOptions } from 'auth0';
export class ClassToTest {
public static getClient(): AuthenticationClient {
let options = {
domain: global.myConfig.DOMAIN,
clientId: global.myConfig.CLIENT,
clientSecret: global.myConfig.SECRET
} as AuthenticationClientOptions;
let auth0 = new AuthenticationClient(options);
return auth0;
}
}
export default ClassToTest;
Now I want to write a unit test that confirms that the right values were passed into options
.
I am trying sth like
import { expect } from "chai";
import * as sinon from 'sinon';
import ClassToTest from "./ClassToTest";
import { AuthenticationClient, AuthenticationClientOptions } from "auth0";
describe("ClassToTest", () => {
beforeEach(() => {
global.myConfig.DOMAIN = 'someValue';
});
afterEach(() => {
sinon.restore();
});
it("uses right options", async function () {
let usedOptions: AuthenticationClientOptions;
sinon.stub(AuthenticationClient.prototype, 'constructor')
.callsFake((opts: AuthenticationClientOptions) => {
usedOptions = opts;
});
expect(usedOptions.domain).to.equal('someValue');
});
})
This gives me:
error TS2345: Argument of type '"constructor"' is not assignable to parameter of type 'keyof AuthenticationClient'.
We can't stub the constructor
of a JS class like that, see issues/1892.
A solution is to use proxyquire to stub out the auth0
module and its AuthenticationClient
class. Besides, we can use .getCall(n).args
to get the arguments of stub for the nth call.
E.g.
classToTest.ts
:
import { AuthenticationClient } from './auth0';
export class ClassToTest {
public static getClient(): AuthenticationClient {
let options = {
domain: global.myConfig.DOMAIN,
clientId: global.myConfig.CLIENT,
clientSecret: global.myConfig.SECRET,
};
let auth0 = new AuthenticationClient(options);
return auth0;
}
}
export default ClassToTest;
auth0.ts
:
// Simulate auth0 module
export class AuthenticationClient {
constructor(options) {}
}
classToTest.test.ts
:
import proxyquire from 'proxyquire';
import sinon from 'sinon';
describe('76519308', () => {
beforeEach(() => {
global.myConfig = global.myConfig || {};
global.myConfig.DOMAIN = 'someValue';
});
it('should pass', () => {
const AuthenticationClientStub = sinon.stub();
const ClassToTest = proxyquire('./classToTest', {
'./auth0': {
AuthenticationClient: AuthenticationClientStub,
},
}).default;
ClassToTest.getClient();
sinon.assert.match(AuthenticationClientStub.getCall(0).args[0].domain, 'someValue');
});
});