在 Meteor 应用程序中,我需要测试一些具有语句的客户端代码
,例如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);
};
});
};
但它仅在直接调用方法时才有效。
我不确定如何使用正确的安全验证来测试我的客户端代码。如何使用经过身份验证的用户测试我的客户端代码?
第一部分:使函数成为导出函数
您只需要将导出的方法也添加到流星方法中。
imports/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
};
然后,可以在服务器脚本中导入此方法:
导入/启动/方法.js
import {foo} from '../api/foo.js'
Meteor.methods({
'foo' : foo
});
因此,可以通过Mateor.call('foo'...(调用它。请注意,回调不必在 foo 的函数头中定义,因为它是由 meteor 自动包装的。
imports/api/foo.tests.js
import {foo} from './foo.js'
if (Meteor.isServer) {
// ... your test setup
const result = foo(...) // call foo directly in your test.
}
这只是在服务器上,现在这里是在客户端上测试的事情:你不会通过 Meteor.call 调用它并测试回调结果。因此,在您的客户端上,您仍然会像以下情况进行测试:
imports/api/foo.tests.js
if (Meteor.isClient) {
// ... your test setup
Meteor.call('foo', ..., function(err, res) {
// assert no err and res...
});
}
附加信息:
我建议您使用 mdg:validated-method,它允许上述相同功能,PLUS 为您提供对方法执行、文档架构验证和灵活性的更复杂的控制。它还记录得足够好,可以让您实现上述要求。
请参阅:https://github.com/meteor/validated-method
第 II 部分:使用用户身份验证运行集成测试
此处有两个选项来测试用户身份验证。它们既有优点也有缺点,并且存在关于什么是更好方法的争论。无论您要测试两者中的哪一个,您都需要编写一个服务器方法,将现有用户添加到给定的角色集。
方法1 - 模拟Meteor.user((和Meter.userid((
这基本上在以下资源中描述/讨论:
一个完整的要点示例
使用 mdg:验证方法或普通方法的示例
使用sinon spy,下面还有我自己通过手动模拟它的答案,但这可能不适用于您的情况,因为它是仅限客户端的。使用 sinon 需要以下软件包: https://github.com/practicalmeteor/meteor-sinon
方法 2 - 复制"真实"应用程序行为
在这种情况下,您可以完全测试而不嘲笑任何东西。您可以创建真实用户并在其他测试中使用他们的数据。
在任何情况下,您都需要一个服务器方法,该方法通过给定的名称和角色创建新用户。请注意,它应该只在名称为 .test.js 的文件中。否则,它可以被视为安全风险。
/imports/api/accounts/accounts.tests.js
Meteor.methods({
createtestUser(name,password, roles, group);
const userId = Accounts.createUser({username:name, password:password});
Roles.addUserToRoles(userId, roles, group);
return userId;
});
注意:我经常听说这是糟糕的测试,我不同意。特别是集成测试应该尽可能地模仿真实行为,并且应该像单元测试那样使用更少的模拟/间谍。