Unit testing 测试meteor-使用单元测试而不是集成测试来测试允许/拒绝

Unit testing 测试meteor-使用单元测试而不是集成测试来测试允许/拒绝,unit-testing,meteor,jasmine,integration-testing,meteor-velocity,Unit Testing,Meteor,Jasmine,Integration Testing,Meteor Velocity,我有一个应用程序代码,它以以下方式限制文档 允许{ 插入:functionuserId,doc{ return!!用户ID }, 更新:functionuserId,doc{ 返回userId&&doc.owner==userId; } } 目前,我只能运行一个进行实际http调用的集成测试。我无法在测试允许/拒绝规则下将组件Meteor当前用户存根到系统外部 如果用户通过身份验证,则应该成功,functiondone{ Meteor.loginWithPassword'shawn@abc.co

我有一个应用程序代码,它以以下方式限制文档

允许{ 插入:functionuserId,doc{ return!!用户ID }, 更新:functionuserId,doc{ 返回userId&&doc.owner==userId; } } 目前,我只能运行一个进行实际http调用的集成测试。我无法在测试允许/拒绝规则下将组件Meteor当前用户存根到系统外部

如果用户通过身份验证,则应该成功,functiondone{ Meteor.loginWithPassword'shawn@abc.com“,”哈哈哈“,函数错误{ 期望被定义; Doc=Docs.插入{标题:“abc”, 类别:'金融'}, 函数错误,id{ 期望被定义; 期望不被定义; 完成; }; }; }; 如果用户未通过身份验证,则应失败,functiondone{ Meteor.logout函数{ doc=Docs.插入{标题:“abc”, 类别:"金融",, 所有者:'1232131'}, 函数错误,id{ 期望不被定义; 完成; }; }; };
这使得我的测试速度非常慢,特别是如果有很多路径需要测试的话。我有没有办法把这个测试转移到一个较低级别的单元测试

此测试测试服务器代码上的执行路径,这是允许/拒绝规则所在的位置

这里的测试没有实现客户机和服务器之间的集成,这正是您的客户机集成测试做得很好的地方

您可以使用单元测试覆盖代码中的所有执行路径,然后进行较少的集成测试,因此您将获得所需的速度

你应该尽可能多地进入较低的层次,但不是全部。您仍然希望确保集成也能正常工作

描述“文档安全规则”的功能{ var_oldAllowRules; 前功能{ var_allowRules=null; //保留旧Docs.allow方法,以便我们可以在后续步骤中恢复 _oldAllowRules=Docs.allow; //重写Docs.allow方法,以便隔离允许规则代码 Docs.allow=函数允许规则{ _allowRules=allowRules; }; }; 毕竟功能{ //还原Docs.allow方法 Docs.allow=_oldAllowRules; }; 它具有“插入拒绝未登录用户访问”功能{ //执行 //您现在可以直接练习allowRules var response=_allowRules.insertnull,{}; //核实 expectresponse.toBefalse; }; 它的“更新允许文档所有者”功能{ //你可以一步完成这一切 expect_allowRules.update1234,{owner:1234}.toBetrue; }; 它的“注销用户的更新被拒绝”功能{ 期望_allowRules.updatenull,{}.toBefalse; }; 它的“非文档所有者的更新拒绝”功能{ expect_allowRules.update1234,{owner:5678}.toBefalse; }; };
此测试在服务器代码上练习执行路径,这是允许/拒绝规则所在的位置

这里的测试没有实现客户机和服务器之间的集成,这正是您的客户机集成测试做得很好的地方

您可以使用单元测试覆盖代码中的所有执行路径,然后进行较少的集成测试,因此您将获得所需的速度

你应该尽可能多地进入较低的层次,但不是全部。您仍然希望确保集成也能正常工作

描述“文档安全规则”的功能{ var_oldAllowRules; 前功能{ var_allowRules=null; //保留旧Docs.allow方法,以便我们可以在后续步骤中恢复 _oldAllowRules=Docs.allow; //重写Docs.allow方法,以便隔离允许规则代码 Docs.allow=函数允许规则{ _allowRules=allowRules; }; }; 毕竟功能{ //还原Docs.allow方法 Docs.allow=_oldAllowRules; }; 它具有“插入拒绝未登录用户访问”功能{ //执行 //您现在可以直接练习allowRules var response=_allowRules.insertnull,{}; //核实 expectresponse.toBefalse; }; 它的“更新允许文档所有者”功能{ //你可以一步完成这一切 expect_allowRules.update1234,{owner:1234}.toBetrue; }; 它的“注销用户的更新被拒绝”功能{ 期望_allowRules.updatenull,{}.toBefalse; }; 它的“非文档所有者的更新拒绝”功能{ expect_allowRules.update1234,{owner:5678}.toBefalse; }; };
建立在流星测试手册的答案之上。。。Stories.allow mock是在加载应用程序代码后定义的。因此,它没有效果 .

如中所述

tests/jasmine文件夹或其子文件夹中以-stubs.js或-stub.js结尾的文件被视为stub,并在应用程序代码之前加载

因此,为了使Meteor测试手册的答案有效,我们必须在-stubs.js文件中定义stub/mock。这就是我在z-security-stubs.js上所做的

注意,我在文件名前面加了“z”,因为meteor按字母顺序加载子目录中相同级别的文件。我们必须确保我们的自定义存根在Velocity自动生成的package-stubs.js和packageMocksSpec.js之后加载

考虑到这一点,z-security-stubs.js可以包含如下内容:

Mongo.Collection.prototype.allow = function(rules){
  this._velocityAllow = rules;
}

Mongo.Collection.prototype.deny = function(rules){
  this._velocityDeny = rules;
}
这将在集合实例的属性中保留对我们的允许/拒绝安全规则的引用,例如文档、文件或集合的任何名称

之后,我们可以引用此属性中的安全函数并做出断言:

describe("Docs security rules", function() {
  var allow;

  beforeEach(function(){
    allow = Docs._velocityAllow;
  });

  it("insert deny access to non-logged in users", function() {
    var response = allow.insert(null, {});
    expect(response).toBe(false);
  });

  it("insert allow access to logged in users", function() {
    var response = allow.insert(true, {});
    expect(response).toBe(true);
  });

  it("update allow access to logged in users who are owners", function() {
    var response = allow.insert(2, {owner: 2});
    expect(response).toBe(true);
  });

  it("update deny access to non-logged in users", function() {
    var response = allow.update(null, {owner: 2});
    expect(response).toBe(false);
  });

  it("update deny access to logged in users who are not owners", function() {
    var response = allow.update(1, {owner: 2});
    expect(response).toBe(false);
  });
});

建立在流星测试手册的答案之上。。。Stories.allow mock是在加载应用程序代码后定义的。因此,它没有效果

如中所述

tests/jasmine文件夹或其子文件夹中以-stubs.js或-stub.js结尾的文件被视为stub,并在应用程序代码之前加载

因此,为了使Meteor测试手册的答案有效,我们必须在-stubs.js文件中定义stub/mock。这就是我在z-security-stubs.js上所做的

注意,我在文件名前面加了“z”,因为meteor按字母顺序加载子目录中相同级别的文件。我们必须确保我们的自定义存根在Velocity自动生成的package-stubs.js和packageMocksSpec.js之后加载

考虑到这一点,z-security-stubs.js可以包含如下内容:

Mongo.Collection.prototype.allow = function(rules){
  this._velocityAllow = rules;
}

Mongo.Collection.prototype.deny = function(rules){
  this._velocityDeny = rules;
}
这将在集合实例的属性中保留对我们的允许/拒绝安全规则的引用,例如文档、文件或集合的任何名称

之后,我们可以引用此属性中的安全函数并做出断言:

describe("Docs security rules", function() {
  var allow;

  beforeEach(function(){
    allow = Docs._velocityAllow;
  });

  it("insert deny access to non-logged in users", function() {
    var response = allow.insert(null, {});
    expect(response).toBe(false);
  });

  it("insert allow access to logged in users", function() {
    var response = allow.insert(true, {});
    expect(response).toBe(true);
  });

  it("update allow access to logged in users who are owners", function() {
    var response = allow.insert(2, {owner: 2});
    expect(response).toBe(true);
  });

  it("update deny access to non-logged in users", function() {
    var response = allow.update(null, {owner: 2});
    expect(response).toBe(false);
  });

  it("update deny access to logged in users who are not owners", function() {
    var response = allow.update(1, {owner: 2});
    expect(response).toBe(false);
  });
});

为什么这个测试包含在“服务器”测试中?我认为。允许规则仅在执行客户端插入时才执行?服务器插入将完全绕过允许规则:刚刚测试过。无法调用null的方法“insert”。我认为Docs.allow重写代码实际上从未被调用过。我认为Jasmine之前需要-我只是更新了我之前使用的答案。这对我不起作用。也许我遗漏了一些输入错误,但似乎我的应用程序代码是在测试代码之前加载的。这意味着“.allow”mock没有在allI调用。我将尝试在本地运行并在此处更新。为什么此测试包含在“服务器”测试中?我认为。允许规则仅在执行客户端插入时才执行?服务器插入将完全绕过允许规则:刚刚测试过。无法调用null的方法“insert”。我认为Docs.allow重写代码实际上从未被调用过。我认为Jasmine之前需要-我只是更新了我之前使用的答案。这对我不起作用。也许我遗漏了一些输入错误,但似乎我的应用程序代码是在测试代码之前加载的。这意味着“.allow”mock在allI没有被调用我将尝试在本地运行并在这里更新。太棒了!我在本地完成了完全相同的解决方案,并希望更改Jasmine,以避免强制您对存根使用z-xxxx.js。是的,但如果我们有多个.allow insert/update链,则上述方法将无法很好地工作,因为上面假设每个集合只有一个u.velocityAllow.insertYou只能有一个insert/update。因此,使用Docs.\u velocityAllow.insert在这里很好,当您有另一个集合时,您可以使用另一个集合。\u velocityAllow.insert您可以随意调用allow多次,每次调用都可以包括插入、更新和删除函数的任意组合。如果函数认为应该允许该操作,则应返回true。否则,它们应该返回false,或者不返回任何未定义的内容。在这种情况下,Meteor将继续搜索集合中的任何其他允许规则。太棒了!我在本地完成了完全相同的解决方案,并希望更改Jasmine,以避免强制您对存根使用z-xxxx.js。是的,但如果我们有多个.allow insert/update链,则上述方法将无法很好地工作,因为上面假设每个集合只有一个u.velocityAllow.insertYou只能有一个insert/update。因此,使用Docs.\u velocityAllow.insert在这里很好,当您有另一个集合时,您可以使用另一个集合。\u velocityAllow.insert您可以随意调用allow多次,每次调用都可以包括插入、更新和删除函数的任意组合。如果函数认为应该允许该操作,则应返回true。否则,它们应该返回false,或者不返回任何未定义的内容。在这种情况下,“流星”将继续搜索 通过集合上的任何其他允许规则。