Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/meteor/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 测试Meteor服务器方法使用经过身份验证的用户调用客户端代码_Javascript_Meteor - Fatal编程技术网

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

Javascript 测试Meteor服务器方法使用经过身份验证的用户调用客户端代码,javascript,meteor,Javascript,Meteor,在Meteor应用程序中,我需要测试一些包含以下语句的客户端代码 Meteor.call('foo', param1, param2, (error, result) => { .... }); 在这些方法中,我进行了安全检查,以确保该方法只能由经过身份验证的用户调用。但是,所有这些测试在测试期间都会失败,因为没有用户经过身份验证 在每个服务器方法中,我都像这样检查用户 if (!Roles.userIsInRole(this.userId, [ ...roles ], group))

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

  });

};
但它仅在直接调用方法时有效


我不确定如何使用正确的安全验证来测试我的客户机代码。如何使用经过身份验证的用户测试客户端代码?

第一部分:使函数成为导出函数

您只需要将导出的方法也添加到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的回调也有问题?不,服务器方法没有问题。它只是从客户端执行的一些代码中调用,我不确定在这种情况下如何模拟经过身份验证的用户。