Reputation: 4363
I would like to stub user
and userId
using sinon-ts
so I can test my server side code that gets results from the database.
If I use plain sinon
I can stub user
and userId
correctly and the test passes. Although it passes Webstorm
shows errors where the returns
method doesn't exist etc so I don't think it is playing well with Typescript
.
sinon - Passes
import {Factory} from 'meteor/dburles:factory';
import {Meteor} from 'meteor/meteor';
import {resetDatabase} from 'meteor/xolvio:cleaner';
import {GiftListCollectionManager} from "../imports/api/collections/GiftListCollection";
import User = Meteor.User;
import { sinon } from 'meteor/practicalmeteor:sinon';
describe("Test", function () {
beforeEach(() => {
resetDatabase();
Factory.define('user', Meteor.users, {
});
currentUser = Factory.create('user');
sinon.stub(Meteor, 'user');
Meteor.user.returns(currentUser);
sinon.stub(Meteor, 'userId');
Meteor.userId.returns(currentUser._id);
});
afterEach(() => {
Meteor.user.restore();
Meteor.userId.restore();
resetDatabase();
});
it("Gets giftlists based on Meteor.userId()", () => {
console.log("Gift lists")
console.log(GiftListCollectionManager.getInstance().getGiftLists());
})
}
I decided to give sinon-ts
a try so I can get no syntax errors shown. I can't seem to get it to stub user
and userId
correctly.
sinon-ts - Failing
import {Meteor} from 'meteor/meteor';
import {resetDatabase} from 'meteor/xolvio:cleaner';
import {GiftListCollectionManager} from "../imports/api/collections/GiftListCollection";
import * as sinon from "ts-sinon";
describe("Test", function () {
let currentUser;
beforeEach(() => {
resetDatabase();
Factory.define('user', Meteor.users, {
});
currentUser = Factory.create('user');
const userStub = sinon.stubObject(Meteor);
userStub.user.returns(currentUser);
const userIdStub = sinon.stubObject(Meteor);
userIdStub.userId.returns(currentUser._id);
});
it("Gets giftlists based on Meteor.userId()", () => {
console.log("Gift lists")
console.log(GiftListCollectionManager.getInstance().getGiftLists());
})
});
Error
I20210322-09:45:44.170(0)? Error: Meteor.userId can only be invoked in method calls or publications.
I20210322-09:45:44.170(0)? at AccountsServer.userId (packages/accounts-base/accounts_server.js:117:13)
I20210322-09:45:44.171(0)? at Object.Meteor.userId (packages/accounts-base/accounts_common.js:339:32)
I20210322-09:45:44.171(0)? at GiftListCollectionManager.getGiftLists (imports/api/collections/GiftListCollection.ts:32:61)
I20210322-09:45:44.171(0)? at Test.<anonymous> (tests/main.ts:66:61)
I20210322-09:45:44.171(0)? at run (packages/meteortesting:mocha-core/server.js:36:29)
I20210322-09:45:44.171(0)? at Context.wrappedFunction (packages/meteortesting:mocha-core/server.js:65:33)
I've spent a lot of time looking around and can't find anything on people stubbing Meteor user
and userId
using sinon-ts
.
What is the correct method of achieving the same results?
Update
Using callsFake throws an exception
import sinon = require('sinon');
sinon.stub(Meteor, 'user').callsFake(() => currentUser);
sinon.stub(Meteor, 'userId').callsFake(() => currentUser._id);
Error
TypeError: sinon.stub(...).callsFake is not a function
at Hook.<anonymous> (tests/main.ts:19:36)
at run (packages/meteortesting:mocha- core/server.js:36:29)
Upvotes: 2
Views: 226
Reputation: 8423
It turned out that sinon-ts
implements "extensions" around sinon to make it work better with TypeScript but it still supports the "default" sinon behaviour.
The function stubs are known to work with Meteor.user()
and Meteor.userId()
and can be access via
import sinon, { stubInterface } from "ts-sinon";
const functionStub = sinon.stub();
or via
import * as tsSinon from "ts-sinon"
const functionStub = tsSinon.default.stub();
Applying this scheme to your current code would result in the following code, that is expected to work with Meteor's user functions:
import {Meteor} from 'meteor/meteor';
import * as sinon from "ts-sinon";
// ... other imports
describe("Test", function () {
let currentUser;
beforeEach(() => {
resetDatabase();
Factory.define('user', Meteor.users, {
});
currentUser = Factory.create('user');
sinon.default.stub(Meteor, 'user').callsFake(() => currentUser);
sinon.default.stub(Meteor, 'userId').callsFake(() => currentUser._id);
});
// ... test units
});
References:
https://github.com/ttarnowski/ts-sinon#sinon-methods
https://sinonjs.org/releases/v9.2.4/stubs/
Upvotes: 2