在 Node.js 中测试模块的内部成员

模块(Module)的内部成员是指没有通过 module.exports 导出的变量或函数。如下面的示例模块:

var A = function() {
  // 执行某些操作
};

module.exports = function B() {
  A();
};

其中函数 A 就是该模块的内部成员,而命名函数表达式(Named Function Expression) B 则是该模块的公开成员。绝大多数情况下,单元测试只关注模块的公开成员,这是因为公开成员代表着模块的接口与功能,而内部成员则与模块的具体实现相关。对模块的内部成员进行测试,意味着测试代码需要了解模块的实现细节,导致测试代码与实现代码高度耦合,进而阻碍日后对代码的重构,这显然违背了单元测试的本意。而且实践 TDD 时,测试先于实现,更谈不上对模块的实现细节进行测试了。

然而凡事都有例外,实践时并不能百分之百地保证测试代码不需要直接访问模块内部成员。下面本文将就两种情况对如何测试模块内部成员进行介绍。

Express 框架 middleware 的依赖问题与解决方案

作为 Node 社区最受欢迎的框架,Express 在沿用 Connect 的 middleware 机制的同时,还提供了在定义路由时使用的 route-specific middleware(下面称“路由中间件”)。路由中间件与 Connect 的 middleware 十分相似,可以用来执行预载入资源或校验请求等操作。然而由于路由中间件的用法非常自由,导致开发时很容易写出难以维护的代码。这篇文章就将介绍路由中间件之间高耦合的问题以及相应的解决方案。

下面是使用路由中间件从数据库载入用户资料的示例,这段代码来自 TJ(Express 的作者)的一个 Screencast

var loadUser = function(req, res, next) {
  User.findById(req.session.userId, function(err, user) {
    if (err) return next(err);
    req.currentUser = user;
    next();
  });
};

app.get('/dashboard', loadUser, function(req, res) {
  res.render('dashboard', { user: req.currentUser });
});

在上面的代码中,我们定义了路由中间件 loadUserloadUser 从数据库中读取用户数据后,将 user 对象通过 reqcurrentUser 属性传递给下一个路由中间件。这种通过 req 对象的属性传递数据的模式在 Express 中很常见。当项目比较小的时候这种模式非常方便易用,可是随着项目不断发展,这种模式会暴露出不少问题,至于具体有哪些问题,请继续往下看。

纯 CSS 实现高度与宽度成比例的效果

最近在做一个产品列表页面,布局如右图所示。页面中有若干个 item,其中每个 item 都向左浮动,并包含在自适应浏览器窗口宽度的父元素中。

item 元素的 CSS 定义如下:

.item {
  float: left;
  margin: 10px 2%;
  width: 21%;
}

这时遇到的一个需求:在保持 item 元素宽高比恒定(如高是宽的 1.618 倍)的情况下,使得 item 元素可以和父元素同比缩放。 我们知道,如果当 item 元素是图片,同时需要保持的宽高比恰好为图片本身的宽高比时,可以设置 item 的 heightauto 即可轻松实现这个需求。然而当 item 元素不是图片或者要保持的宽高比和图片本身的宽高比不同时,这个需求显得很难直接用 CSS 实现。

为此我放弃 CSS,直接用 JavaScript 绑定 windowonresize 事件来动态获取每个 item 的宽度,从而计算并设置其高度。

我一直在使用这个解决方案,直到今天调整样式时,突然想到这个需求竟然是可以只使用 CSS 解决的。

我的 Vim 常用插件和键位映射配置

写给那些从来不使用别人的 Vim 的人

记得刚接触 Mac 时,我是用 Coda 写代码的,写了很长很长时间。之后 Sublime Text 大火,便也尝试了几个月。到了如今,已经不知不觉地当了两年的 Vim 党。

Vim 是个神奇的编辑器,不论编辑哪种语言的代码,总能找到一些插件来提升编码体验。就算是用了挺久的 Vim,也时不时地会听到别人说起一些自己从没用过但是很实用的技巧。虽然有时也会怀念 Coda 漂亮的界面和方便的远程文件管理,会怀念 Sublime Text  功能强大却又容易上手的设计理念。但是从没有一种理由让我换用其它编辑器,因为总会有一个 Vim 插件能够填补你内心深处的不满足。

我主要用 Vim 写些网页前后端代码,下面我将分享一些我在用的 Vim 插件和键位映射配置,完整的 .vimrc 文件可以在这里看到。

减少异步嵌套,Express-promise

在使用 Express 框架开发网站或 API 时,经常会因为 Node.js 的异步流程造成逻辑代码中嵌套回调函数过多的问题。这时可以考虑使用 Promise 来简化这个流程。关于 Promise 可以参考以下资料:

http://www.infoq.com/cn/news/2011/09/js-promise http://martinfowler.com/bliki/JavascriptPromise.html

现在 Node.js 很多 ORM/ODM 都通过 Promise 来返回查询、执行结果,而普通的 Node.js 风格回调函数可以很容易的转换成 Promise。

为此,我为 Express 框架开发了一个 middleware 用来更方便地使用 Promise。

Page 1 / 5 »