使用经过身份验证的用户在客户端代码中测试 Meteor 服务器方法调用



在 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;
});

注意:我经常听说这是糟糕的测试,我不同意。特别是集成测试应该尽可能地模仿真实行为,并且应该像单元测试那样使用更少的模拟/间谍。

最新更新