blog icon indicating copy to clipboard operation
blog copied to clipboard

使用karma实现mock

Open renaesop opened this issue 8 years ago • 0 comments

karma是一个著名的浏览器测试框架,他的特色是启动一个nodejs服务器,在浏览器端通过http下载脚本,并通过websocket实现karma和浏览器实现双向通信。

网上甚少有使用karma做mock的教程。但是因为karma使用了connect模块,有中间件的能力,因此值得一试。

引入karma

karma官方支持的是jasmine,所以省事一点就直接用jasmine(不过这货返回promise没有官方支持)。

  • 在项目中新建文件karma.conf.js
module.exports = config => {
    config.set({
        basePath: './test',
        files: ['**/*.spec.js'],
        browsers : [
          'Chrome',
        ],
        frameworks: ['jasmine'],
        singleRun: true,
    });
}
  • 新建 test/entry.spec.js
describe('Hello, test', () => {
    it('should work', () => {
        const data = 0;
        expect(data).toEqual(0);
    });
});
  • 安装依赖 npm i karma karma-jasmine karma-chrome-launcher jasmine-core -D

  • 执行测试 node_modules/.bin/karma start

执行之后,可以看到浏览器被自动打开然后关闭,控制台出现一片绿色提示,表示测试成功了。

实现mock

吐槽一下,karma深受Java/AngularJS的影响,什么都搞依赖注入,怪恶心的。

karma支持插件,插件的结构应该如此:

.......
// optional
fn.$injector = [xxx, xxx ,xxx]

module.exports = {
    `${plugin type}:${plugin name}`: [`${fn type, factory or value}`, fn]
}

插件主要有4种类型分别是 frameworks, reporters, launchers and preprocessors, 另外还有我们要用的middleware。

插件默认会接收到config作为参数(就是我们写的配置文件),也可以通过对fn执行$injector属性指定fn被注入的参数。

如此我们就开始实现一个我们的middleware。

  • 新建 test/mock/middleware.js 文件
// 比较简单,当路径匹配到指定的mockUriStart时
// 则加载processors下的模块处理请求

function mockFactory(config) {
  const mockUrl = config.mockUriStart || '/mock-api/';
  return function (req, res, next) {
    if (req.url.indexOf(mockUrl) === 0) {
      const path = req.url.slice(mockUrl.length);
      try {
        const processor = require(`./processors/${path}`);
        processor(req, res);
      }
      catch (e) {
        next();
      }
    }
    else {
      next();
    }
  };
};
// 我们只需要config,因此就不指定$injector属性了
module.exports = {
  'middleware:mock': ['factory', mockFactory]
};
  • 新建 test/mock/processors/simple.js文件
module.exports = function (req, res) {
  res.end('Simple data');
};
  • 修改karma.conf.js, 这里有个大坑点,如果你想加载不处于node_modules的插件,则需要手动在plugins中添加。但是一旦有了plugins选项,那么所有的插件加载都要手动添加,包括在node_modules中的插件。
module.exports = config => {
    config.set({
        basePath: './test',
        files: ['**/*.spec.js'],
        browsers : [
          'Chrome',
        ],
        frameworks: ['jasmine'],
        middleware: ['mock'],
        plugins: [
            require('./test/mock/middleware'),
            require('karma-jasmine'),
            require('karma-chrome-launcher'),
        ],
        singleRun: true,
    });
}
  • 修改 test/entry.spec.js
describe('Hello, test', () => {
    it('should work', (done) => {
       const xhr = new XMLHttpRequest();
       xhr.open('GET', '/mock-api/simple', true);
       xhr.onreadystatechange = function () {
            if (xhr.readyState === 4) {
               console.log(xhr.response);
               done();
             }
      };
    xhr.send(null);
    });
});
  • 执行测试 node_modules/.bin/karma start

将会看到karma的控制台有LOG: 'Simple data'的字样。

至此,就完成了一个简单的mock server,只要扩充mock中间件对路由的处理逻辑或者让mock中间件做其他mock服务器的代理,就可以拥有更加完整的功能。

renaesop avatar Nov 04 '16 08:11 renaesop