我有一个以下列方式限制文档的应用程序代码
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();
});
});
});
这使得我的测试非常慢,特别是如果我想测试很多路径。我有办法将此测试转移到较低级别的单元测试吗?
答案 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.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);
});
});
答案 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);
});
});