问题描述
我想使用 user
存根 userId
和 sinon-ts
,以便我可以测试从数据库中获取结果的服务器端代码。
如果我使用普通的 sinon
,我可以正确地存根 user
和 userId
并且测试通过。虽然它通过 Webstorm
显示错误,其中 returns
方法不存在等,所以我认为它与 Typescript
配合得不好。
sinon - 传球
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());
})
}
我决定尝试一下 sinon-ts
,这样我就不会显示任何语法错误。我似乎无法正确地存根 user
和 userId
。
sinon-ts - 失败
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',{
});
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());
})
});
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)
我花了很多时间环顾四周,但找不到任何关于使用 user
存根 Meteor userId
和 sinon-ts
的人的任何信息。
达到相同结果的正确方法是什么?
更新
使用callsFake会抛出异常
import sinon = require('sinon');
sinon.stub(Meteor,'user').callsFake(() => currentUser);
sinon.stub(Meteor,'userId').callsFake(() => currentUser._id);
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)
解决方法
事实证明,sinon-ts
围绕 sinon 实现了“扩展”,以使其更好地与 TypeScript 配合使用,但它仍然支持“默认” sinon 行为。
已知 function stubs 可以与 Meteor.user()
和 Meteor.userId()
一起使用,并且可以通过
import sinon,{ stubInterface } from "ts-sinon";
const functionStub = sinon.stub();
或通过
import * as tsSinon from "ts-sinon"
const functionStub = tsSinon.default.stub();
将此方案应用于您当前的代码将产生以下代码,预计可与 Meteor 的用户功能一起使用:
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
});
参考文献: