Meteor / Jasmine / Velocity:如何测试需要登录用户的服务器方法?
Meteor / Jasmine / Velocity : how to test a server method requiring logged in user?
使用 velocity/jasmine,我对如何测试需要有当前登录用户的服务器端方法有点困惑。有没有办法让 Meteor 认为用户是通过 stub/fake 登录的?
myServerSideModel.doThisServerSideThing = function(){
var user = Meteor.user();
if(!user) throw new Meteor.Error('403', 'not-autorized');
}
Jasmine.onTest(function () {
describe("doThisServerSideThing", function(){
it('should only work if user is logged in', function(){
// this only works on the client :(
Meteor.loginWithPassword('user','pwd', function(err){
expect(err).toBeUndefined();
});
});
});
});
您要测试什么,为什么需要用户登录?我拥有的大多数方法都需要一个用户对象,我将用户对象传递给它。这允许我在没有实际登录的情况下从测试中调用。所以在代码的实际 运行 中我会通过...
var r = myMethod(Meteor.user());
但是当 运行 从测试中我会打电话给...
it('should be truthy', function () {
var r = myMethod({_id: '1', username: 'testUser', ...});
expect(r).toBeTruthy();
});
您可以将用户添加到您的测试套件中。您可以通过在 服务器端 测试脚本中填充这些用户来做到这一点:
类似于:
Jasmine.onTest(function () {
Meteor.startup(function() {
if (!Meteor.users.findOne({username:'test-user'})) {
Accounts.createUser
username: 'test-user'
... etc
然后,一个好的策略可能是在测试中使用 beforeAll
登录(这是 client 端):
Jasmine.onTest(function() {
beforeAll(function(done) {
Meteor.loginWithPassword('test-user','pwd', done);
}
}
这是假设您的测试尚未登录。您可以通过检查 Meteor.user()
并在 afterAll
中正确注销等来使它更有趣。请注意如何轻松地将 done
回调传递给许多 Accounts
函数。
本质上,您不必模拟用户。只需确保您在 Velocity/Jasmine 数据库中拥有正确的用户和正确的角色即可。
假设您有这样的服务器端方法:
Meteor.methods({
serverMethod: function(){
// check if user logged in
if(!this.userId) throw new Meteor.Error('not-authenticated', 'You must be logged in to do this!')
// more stuff if user is logged in...
// ....
return 'some result';
}
});
您不需要在执行该方法之前制作Meteor.loginWithPassword。您所要做的就是通过更改方法函数调用的 this
上下文来存根 this.userId
。
所有定义的流星方法都可用于 Meteor.methodMap
对象。所以只需使用不同的 this
上下文
调用该函数
describe('Method: serverMethod', function(){
it('should error if not authenticated', function(){
var thisContext = {userId: null};
expect(Meteor.methodMap.serverMethod.call(thisContext).toThrow();
});
it('should return a result if authenticated', function(){
var thisContext = {userId: 1};
var result = Meteor.methodMap.serverMethod.call(thisContext);
expect(result).toEqual('some result');
});
});
编辑:此解决方案仅在 Meteor <= 1 上进行了测试。0.x
我认为 Meteor.server.method_handlers["nameOfMyMethod"]
允许您 call/apply Meteor 方法并至少在当前版本 (1.3.3) 中提供 this
作为第一个参数
this.userId = userId;
Meteor.server.method_handlers["cart/addToCart"].apply(this, arguments);
使用 velocity/jasmine,我对如何测试需要有当前登录用户的服务器端方法有点困惑。有没有办法让 Meteor 认为用户是通过 stub/fake 登录的?
myServerSideModel.doThisServerSideThing = function(){
var user = Meteor.user();
if(!user) throw new Meteor.Error('403', 'not-autorized');
}
Jasmine.onTest(function () {
describe("doThisServerSideThing", function(){
it('should only work if user is logged in', function(){
// this only works on the client :(
Meteor.loginWithPassword('user','pwd', function(err){
expect(err).toBeUndefined();
});
});
});
});
您要测试什么,为什么需要用户登录?我拥有的大多数方法都需要一个用户对象,我将用户对象传递给它。这允许我在没有实际登录的情况下从测试中调用。所以在代码的实际 运行 中我会通过...
var r = myMethod(Meteor.user());
但是当 运行 从测试中我会打电话给...
it('should be truthy', function () {
var r = myMethod({_id: '1', username: 'testUser', ...});
expect(r).toBeTruthy();
});
您可以将用户添加到您的测试套件中。您可以通过在 服务器端 测试脚本中填充这些用户来做到这一点:
类似于:
Jasmine.onTest(function () {
Meteor.startup(function() {
if (!Meteor.users.findOne({username:'test-user'})) {
Accounts.createUser
username: 'test-user'
... etc
然后,一个好的策略可能是在测试中使用 beforeAll
登录(这是 client 端):
Jasmine.onTest(function() {
beforeAll(function(done) {
Meteor.loginWithPassword('test-user','pwd', done);
}
}
这是假设您的测试尚未登录。您可以通过检查 Meteor.user()
并在 afterAll
中正确注销等来使它更有趣。请注意如何轻松地将 done
回调传递给许多 Accounts
函数。
本质上,您不必模拟用户。只需确保您在 Velocity/Jasmine 数据库中拥有正确的用户和正确的角色即可。
假设您有这样的服务器端方法:
Meteor.methods({
serverMethod: function(){
// check if user logged in
if(!this.userId) throw new Meteor.Error('not-authenticated', 'You must be logged in to do this!')
// more stuff if user is logged in...
// ....
return 'some result';
}
});
您不需要在执行该方法之前制作Meteor.loginWithPassword。您所要做的就是通过更改方法函数调用的 this
上下文来存根 this.userId
。
所有定义的流星方法都可用于 Meteor.methodMap
对象。所以只需使用不同的 this
上下文
describe('Method: serverMethod', function(){
it('should error if not authenticated', function(){
var thisContext = {userId: null};
expect(Meteor.methodMap.serverMethod.call(thisContext).toThrow();
});
it('should return a result if authenticated', function(){
var thisContext = {userId: 1};
var result = Meteor.methodMap.serverMethod.call(thisContext);
expect(result).toEqual('some result');
});
});
编辑:此解决方案仅在 Meteor <= 1 上进行了测试。0.x
我认为 Meteor.server.method_handlers["nameOfMyMethod"]
允许您 call/apply Meteor 方法并至少在当前版本 (1.3.3) 中提供 this
作为第一个参数
this.userId = userId;
Meteor.server.method_handlers["cart/addToCart"].apply(this, arguments);