我正在我的 Sails 应用程序的模型、控制器和服务上设置单元测试。在测试我的用户模型时,我偶然发现了一个令人困惑的问题。摘录User.js
:
module.exports = {
attributes: {
username: {
type: 'string',
required: true
},
[... other attributes...] ,
isAdmin: {
type: 'boolean',
defaultsTo: false
},
toJSON: function() {
var obj = this.toObject();
// Don't send back the isAdmin attribute
delete obj.isAdmin;
delete obj.updatedAt;
return obj;
}
}
}
以下是我的test.js
,旨在与 mocha 一起运行。请注意,我在蓝图配置中打开了pluralize
标志。此外,我使用sails-ember-blueprints来获得符合Ember Data 的蓝图。所以我的请求必须看起来像{user: {...}}
.
// Require app factory
var Sails = require('sails/lib/app');
var assert = require('assert');
var request = require('supertest');
// Instantiate the Sails app instance we'll be using
var app = Sails();
var User;
before(function(done) {
// Lift Sails and store the app reference
app.lift({
globals: true,
// load almost everything but policies
loadHooks: ['moduleloader', 'userconfig', 'orm', 'http', 'controllers', 'services', 'request', 'responses', 'blueprints'],
}, function() {
User = app.models.user;
console.log('Sails lifted!');
done();
});
});
// After Function
after(function(done) {
app.lower(done);
});
describe.only('User', function() {
describe('.update()', function() {
it('should modify isAdmin attribute', function (done) {
User.findOneByUsername('skippy').exec(function(err, user) {
if(err) throw new Error('User not found');
user.isAdmin = false;
request(app.hooks.http.app)
.put('/users/' + user.id)
.send({user:user})
.expect(200)
.expect('Content-Type', /json/)
.end(function() {
User.findOneByUsername('skippy').exec(function(err, user) {
assert.equal(user.isAdmin, false);
done();
});
});
});
});
});
});
在我设置将阻止对 User.isAdmin 进行写访问的策略之前,我希望我的 user.isAdmin 属性会被此请求更新。在运行测试之前,我的用户的 isAdmin 标志设置为 true。运行测试显示标志未更新:
1) User .update() should modify isAdmin attribute:
Uncaught AssertionError: true == false
这更令人费解,因为在客户端运行的以下 QUnit 测试确实更新了 isAdmin 属性,尽管它无法判断它是否已更新,因为我从 User.toJSON() 中的有效负载中删除了 isAdmin。
var user;
module( "user", {
setup: function( assert ) {
stop(2000);
// Authenticate with user skippy
$.post('/auth/local', {identifier: 'skippy', password: 'Guru-Meditation!!'}, function (data) {
user = data.user;
}).always(QUnit.start);
}
, teardown: function( assert ) {
$.get('/logout', function(data) {
});
}
});
asyncTest("PUT /users with isAdmin attribute should modify it in the db and return the user", function () {
stop(1000);
user.isAdmin = true;
$.ajax({
url: '/users/' + user.id,
type: 'put',
data: {user: user},
success: function (data) {
console.log(data);
// I can not test isAdmin value here
equal(data.user.firstName, user.firstName, "first name should not be modified");
start();
},
error: function (reason) {
equal(typeof reason, 'object', 'reason for failure should be an object');
start();
}
});
});
在 mongoDB 控制台中:
> db.user.find({username: 'skippy'});
{ "_id" : ObjectId("541d9b451043c7f1d1fd565a"), "isAdmin" : false, ..., "username" : "skippy" }
更令人费解的是,注释掉delete obj.isAdmin
会使User.toJSON()
mocha 测试通过!
所以,我想知道:
- Waterline 模型上的 toJSON() 方法是否仅用于输出过滤?还是对update()等写操作有影响。
- 这个问题可能与超测有关吗?由于我的 QUnit 测试中的 jQuery.ajax() 确实修改了 isAdmin 标志,所以超测试请求没有修改是很奇怪的。
任何建议都非常感谢。