测试流星测试允许/拒绝单元测试而不是集成测试

时间:2015-01-30 00:00:10

标签: unit-testing meteor jasmine integration-testing meteor-velocity

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

Docs.allow({
  insert: function(userId, doc){
    return !!userId
  },
  update: function(userId, doc){
    return userId && doc.owner == userId;
  }
})

目前,我只能运行进行实际http调用的集成测试。我无法将被测系统外的组件(Meteor当前用户)存根(允许/拒绝规则)。

it("should succeed if user is authenticated", function(done) {
    Meteor.loginWithPassword(’shawn@abc.com', ‘hahaha', function(err){
        expect(err).toBe(undefined);
        Doc = Docs.insert({title: 'abc', 
                           category: 'Finance'}, 
                          function(err, id){
                              expect(err).toBeUndefined();
                              expect(id).not.toBeUndefined();
                              done();
                          });
    });
});

it("should fail if user is not authenticated", function(done) {
    Meteor.logout(function(){
        doc = Docs.insert({title: 'abc', 
                           category: 'Finance', 
                           owner: '1232131'}, 
                          function(err, id){
                              expect(err).not.toBeUndefined();
                              done();
                          });
    });
});

这使得我的测试非常慢,特别是如果我想测试很多路径。我有办法将此测试转移到较低级别的单元测试吗?

2 个答案:

答案 0 :(得分:4)

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

https://github.com/Sanjo/meteor-jasmine#stubs中所述,

  

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

因此,为了使Meteor Test Manual的答案有效,我们必须在-stubs.js文件中定义存根/模拟。这就是我在z-security-stubs.js上所做的。

注意我用'z'作为文件名前缀,因为meteor按字母顺序加载文件在同一级别的子目录中。我们必须确保在Velocity自动生成package-stubs.jspackageMocksSpec.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);
  });
});

答案 1 :(得分:0)

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

此处的测试不会在客户端与服务器之间进行集成,而是客户端集成测试的效果非常好。

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

你应该尽可能多地进入较低级别,但不是一切。您仍然希望确保集成也有效。

describe('Doc security rules', function () {

  var _oldAllowRules;

  beforeAll(function () {
    var _allowRules = null;

    // keep hold of the old Docs.allow method so we can restore in the after step
    _oldAllowRules = Docs.allow;

    // override the Docs.allow method so we can isolate the allow rules code
    Docs.allow = function (allowRules) {
      _allowRules = allowRules;
    };
  });

  afterAll(function () {
    // restore the Docs.allow method 
    Docs.allow = _oldAllowRules;
  });

  it('insert deny access to non-logged in users', function () {
    // Execute
    // you can now exercise the allowRules directly 
    var response = _allowRules.insert(null, {});

    // Verify
    expect(response).toBe(false);
  });

  it('update allows for doc owner', function () {
    // you can do it all with one step
    expect(_allowRules.update(1234, {owner: 1234})).toBe(true);
  });

  it('update denies for logged out user', function () {
    expect(_allowRules.update(null, {})).toBe(false);
  });

  it('update denies for non document owner', function () {
    expect(_allowRules.update(1234, {owner: 5678})).toBe(false);
  });

});