【发布时间】:2012-12-04 18:53:11
【问题描述】:
乡亲,
我们的项目规模正在迅速增长,我想成为一名优秀的 JS 公民,并在为时已晚之前实施测试。我们正在使用带有 Backbone Layoutmanager 和 Handlebars 模板的 Backbone 创建我们的前端,我已经阅读了 some excellent 博客文章,了解如何使用 Jasmine 和 Jasmine-Jquery 测试 Backbone 驱动的应用程序和Sinon,所以我决定去。
但是,我们的设置有点不典型,因为我们使用 RequireJS 模块、使用 Layoutmanager 增强 Backbone 以及预编译 Handlebars 模板。我们正在由这些库的创建者异步预编译模板as is suggested,在我意识到任何类型的异步 jQuery/Ajax 调用都不起作用之前,我花了一整天的大部分时间敲打我的头使用 Jasmine 运行应用程序。
试图使 $.ajax(...) 调用与 async: false 同步并没有这样做,并且深入研究 Layoutmanager JS 源代码,我发现这一切都是异步发生的。
无论如何,这就是我最终使预编译工作的方式:
Backbone.LayoutManager.configure({
manage: false,
prefix: "app/templates/",
fetch: function(path) {
var done;
var that = this;
// Concatenate the file extension.
path = path + ".html";
runs(function() {
if (!JST[path]) {
done = that.async()
return $.ajax({ url: app.root + path, async: false }).then(
//Successhandler
function(contents) {
JST[path] = Handlebars.compile(contents);
JST[path].__compiled__ = true;
done(JST[path]);
},
//Errorhandler
function(jqXHR, textStatus, errorThrown) {
//Feil ved lasting av template
//TODO logg feil på en eller annen måte
}
);
}
// If the template hasn't been compiled yet, then compile.
if (!JST[path].__compiled__) {
JST[path] = Handlebars.compile(JST[path]);
JST[path].__compiled__ = true;
}
});
waitsFor(function() {
return done;
}, "loading template", 500);
return JST[path];
},
// Override render to use Handlebars
render: function(template, context) {
return template(context);
}
});
解决方案是将异步逻辑包装在 runs 和 waitFor 中。
现在回答问题: 我不认为这是一个最佳解决方案,因为它迫使我复制 app.js 只是为了包装异步调用。有没有更好的方法来解决这个问题?
如果还不够公平,希望其他人从这篇文章中吸取教训。
【问题讨论】:
标签: javascript unit-testing templates backbone.js jasmine