Javascript 测试Meteor服务器方法使用经过身份验证的用户调用客户端代码
在Meteor应用程序中,我需要测试一些包含以下语句的客户端代码Javascript 测试Meteor服务器方法使用经过身份验证的用户调用客户端代码,javascript,meteor,Javascript,Meteor,在Meteor应用程序中,我需要测试一些包含以下语句的客户端代码 Meteor.call('foo', param1, param2, (error, result) => { .... }); 在这些方法中,我进行了安全检查,以确保该方法只能由经过身份验证的用户调用。但是,所有这些测试在测试期间都会失败,因为没有用户经过身份验证 在每个服务器方法中,我都像这样检查用户 if (!Roles.userIsInRole(this.userId, [ ...roles ], group))
Meteor.call('foo', param1, param2, (error, result) => { .... });
在这些方法中,我进行了安全检查,以确保该方法只能由经过身份验证的用户调用。但是,所有这些测试在测试期间都会失败,因为没有用户经过身份验证
在每个服务器方法中,我都像这样检查用户
if (!Roles.userIsInRole(this.userId, [ ...roles ], group)) {
throw new Meteor.Error('restricted', 'Access denied');
}
我已经读到我们应该直接导出服务器方法并直接测试它们,实际上我是为服务器方法测试而这样做的,但这是不可能的,因为我需要测试依赖于Meteor.call的客户机代码
我当然也不想让if(Meteor.isTest | | | Meteor.isAppTest){…}
到处都是
我想也许可以这样包装我的导出方法:
export default function methodsWrapper(methods) {
Object.keys(methods).forEach(method => {
const fn = methods[method];
methods[method] = (...args) => {
const user = Factory.create('user', { roles: { 'default': [ 'admin' ] } });
return fn.call({ userId: user._id }, ...args);
};
});
};
但它仅在直接调用方法时有效
我不确定如何使用正确的安全验证来测试我的客户机代码。如何使用经过身份验证的用户测试客户端代码?第一部分:使函数成为导出函数
您只需要将导出的方法也添加到meteor方法中
导入/api/foo.js
export const foo = function(param1, param2){
if (!Roles.userIsInRole(this.userId, [ ...roles ], group)) {
throw new Meteor.Error('restricted', 'Access denied');
}
//....and other code
};
import {foo} from '../api/foo.js'
Meteor.methods({
'foo' : foo
});
import {foo} from './foo.js'
if (Meteor.isServer) {
// ... your test setup
const result = foo(...) // call foo directly in your test.
}
if (Meteor.isClient) {
// ... your test setup
Meteor.call('foo', ..., function(err, res) {
// assert no err and res...
});
}
Meteor.methods({
createtestUser(name,password, roles, group);
const userId = Accounts.createUser({username:name, password:password});
Roles.addUserToRoles(userId, roles, group);
return userId;
});
然后可以在服务器脚本中导入此方法:
导入/startup/methods.js
export const foo = function(param1, param2){
if (!Roles.userIsInRole(this.userId, [ ...roles ], group)) {
throw new Meteor.Error('restricted', 'Access denied');
}
//....and other code
};
import {foo} from '../api/foo.js'
Meteor.methods({
'foo' : foo
});
import {foo} from './foo.js'
if (Meteor.isServer) {
// ... your test setup
const result = foo(...) // call foo directly in your test.
}
if (Meteor.isClient) {
// ... your test setup
Meteor.call('foo', ..., function(err, res) {
// assert no err and res...
});
}
Meteor.methods({
createtestUser(name,password, roles, group);
const userId = Accounts.createUser({username:name, password:password});
Roles.addUserToRoles(userId, roles, group);
return userId;
});
因此可以通过Mateor.call('foo'…)调用它。注意,回调不必在foo的函数头中定义,因为它是由meteor自动包装的
导入/api/foo.tests.js
export const foo = function(param1, param2){
if (!Roles.userIsInRole(this.userId, [ ...roles ], group)) {
throw new Meteor.Error('restricted', 'Access denied');
}
//....and other code
};
import {foo} from '../api/foo.js'
Meteor.methods({
'foo' : foo
});
import {foo} from './foo.js'
if (Meteor.isServer) {
// ... your test setup
const result = foo(...) // call foo directly in your test.
}
if (Meteor.isClient) {
// ... your test setup
Meteor.call('foo', ..., function(err, res) {
// assert no err and res...
});
}
Meteor.methods({
createtestUser(name,password, roles, group);
const userId = Accounts.createUser({username:name, password:password});
Roles.addUserToRoles(userId, roles, group);
return userId;
});
这只是在服务器上,现在需要在客户端上进行测试:您不会通过Meteor.call调用它并测试回调结果。因此,在您的客户机上,您仍然需要进行以下测试:
导入/api/foo.tests.js
export const foo = function(param1, param2){
if (!Roles.userIsInRole(this.userId, [ ...roles ], group)) {
throw new Meteor.Error('restricted', 'Access denied');
}
//....and other code
};
import {foo} from '../api/foo.js'
Meteor.methods({
'foo' : foo
});
import {foo} from './foo.js'
if (Meteor.isServer) {
// ... your test setup
const result = foo(...) // call foo directly in your test.
}
if (Meteor.isClient) {
// ... your test setup
Meteor.call('foo', ..., function(err, res) {
// assert no err and res...
});
}
Meteor.methods({
createtestUser(name,password, roles, group);
const userId = Accounts.createUser({username:name, password:password});
Roles.addUserToRoles(userId, roles, group);
return userId;
});
其他信息:
我建议您使用mdg:validatedmethod,它允许使用上述相同的功能,并为您提供对方法执行、文档模式验证和灵活性的更复杂控制。它的文档也足够好,可以让您实现上述需求
见:
第二部分:使用用户身份验证运行集成测试
这里有两个选项来测试用户身份验证。它们既有优点也有缺点,关于什么是更好的方法存在争议。无论测试哪一个角色,都需要编写一个服务器方法,将现有用户添加到给定的角色集中
方法1-模仿Meteor.user()和Meter.userid()
这在以下参考资料中进行了基本描述/讨论:
使用sinon需要以下软件包:
方法2-复制“真实”应用程序行为
在这种情况下,您可以完全测试,而无需模拟任何内容。您可以创建真实的用户,并在其他测试中使用他们的数据
在任何情况下,您都需要一个服务器方法,该方法根据给定的名称和角色创建一个新用户。请注意,它应该仅位于名为.test.js的文件中。否则,可将其视为安全风险
/imports/api/accounts/accounts.tests.js
export const foo = function(param1, param2){
if (!Roles.userIsInRole(this.userId, [ ...roles ], group)) {
throw new Meteor.Error('restricted', 'Access denied');
}
//....and other code
};
import {foo} from '../api/foo.js'
Meteor.methods({
'foo' : foo
});
import {foo} from './foo.js'
if (Meteor.isServer) {
// ... your test setup
const result = foo(...) // call foo directly in your test.
}
if (Meteor.isClient) {
// ... your test setup
Meteor.call('foo', ..., function(err, res) {
// assert no err and res...
});
}
Meteor.methods({
createtestUser(name,password, roles, group);
const userId = Accounts.createUser({username:name, password:password});
Roles.addUserToRoles(userId, roles, group);
return userId;
});
注意:我经常听说这是糟糕的测试,我不同意。尤其是集成测试应该尽可能地模仿真实的行为,并且应该像单元测试那样使用较少的模拟/监视。谢谢你的回答,但正如我所说的,我不能在客户端代码中删除Meteor.call
,而这正是我需要测试和验证的代码。我在测试服务器方法方面没有问题,我确实通过单元测试对其进行了独立测试,但这是在集成测试中,以确保UI的行为符合预期,并且被测试的代码是异步的,调用服务器方法是其任务的一部分..您使用mocha进行测试吗?好的,只是为了正确地理解您,您现在的问题是只有未注册的用户(角色身份验证失败)还是Meteor.call的回调也有问题?不,服务器方法没有问题。它只是从客户端执行的一些代码中调用,我不确定在这种情况下如何模拟经过身份验证的用户。