用于节点 JS 验收测试的开发 API

Posted

技术标签:

【中文标题】用于节点 JS 验收测试的开发 API【英文标题】:Development API for node JS Acceptance Tests 【发布时间】:2016-11-23 21:17:01 【问题描述】:

我已经为我的库创建了验收测试。当库发布时,它将使用尚未访问的外部 API 服务。所以我创建了一个模拟 json api 服务器,它返回所需的 JSON 进行测试。为了让测试通过,我必须在发出请求的文件中手动更改 API url。

我想知道是否有办法在运行验收测试时使用模拟 API url,并在不运行验收测试时恢复到实时 URL。下面是带有实时 URL 的代码的 sn-p。

return fetch('http://liveURL.com/api')
  .then(response => 
    if (response.status === 200) 
      return response.json()
        .then(myResponse => 
          var theResponse = myResponse.id;

          return theResponse;
        );
     else 
      return response.json().then(error => 
        throw new Error(error.error);
      );
    
  );

仅在运行验收测试时我想要做的是更改 url,'http://liveURL.com/api',我收到的请求来自 'http://localhost:3000/api'。

我使用的模拟服务器可以在这里找到:https://github.com/typicode/json-server

编辑:在回答 Bens 的问题时,这是我的 package.json,我试图在其中设置 NODE_ENV


  "name": "my-lib",
  "version": "0.1.0",
  "description": "",
  "main": "lib/myLib",
  "private": true,
  "scripts": 
    "lint": "gulp lint",
    "pretest": "npm run lint",
    "test": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter spec \"test/unit/**/*.spec.js\"",
    "acceptance-test": "NODE_ENV=test cucumberjs",
    "build": "gulp build"
  ,
  "author": "Me",
  "license": "ISC",
  "devDependencies": 
    "babel-preset-es2015": "^6.16.0",
    "babel-register": "^6.16.3",
    "babelify": "^7.3.0",
    "browserify": "^13.1.0",
    "chai": "^3.5.0",
    "chai-as-promised": "^5.3.0",
    "config-browserify": "^1.0.5",
    "cors": "^2.8.1",
    "cucumber": "^0.10.3",
    "eslint": "^3.0.1",
    "eslint-teamcity": "^1.1.0",
    "express": "^4.14.0",
    "gulp": "^3.9.1",
    "gulp-eslint": "^3.0.1",
    "gulp-sourcemaps": "^1.6.0",
    "gulp-uglify": "^2.0.0",
    "isomorphic-fetch": "^2.2.1",
    "istanbul": "v1.1.0-alpha.1",
    "jsdom": "^9.8.3",
    "json-server": "^0.9.1",
    "mocha": "^2.5.3",
    "mocha-jsdom": "^1.1.0",
    "mocha-teamcity-reporter": ">=0.0.1",
    "nock": "^9.0.0",
    "node-localstorage": "^1.3.0",
    "portscanner": "^2.1.0",
    "proxyquire": "^1.7.10",
    "selenium-server": "^2.53.0",
    "selenium-webdriver": "^2.53.2",
    "semver": "^5.3.0",
    "serve-static": "^1.11.1",
    "sinon": "^1.17.4",
    "sinon-chai": "^2.8.0",
    "vinyl-buffer": "^1.0.0",
    "vinyl-source-stream": "^1.1.0",
    "watchify": "^3.7.0"
  ,
  "dependencies": 
    "config": "^1.21.0"
  

我在 world.js 中创建了两个服务器。一台运行库的服务器在端口 23661 上,另一台服务器在端口 3000 上运行假 api。这可以在下面看到

'use strict';

const SeleniumServer = require('selenium-webdriver/remote').SeleniumServer;
 const webdriver = require('selenium-webdriver');
const server = new SeleniumServer(require('selenium-server').path, port: 4444);
const serveStatic = require('serve-static');
const express = require('express');
const chaiAsPromised = require('chai-as-promised');
const chai = require('chai');
const jsonServer = require('json-server');
const cors = require('cors');

chai.should();
chai.use(chaiAsPromised);

const testServer = jsonServer.create();
const router = jsonServer.router('db.json');

testServer.use(cors());
testServer.options('*', cors());
testServer.use(router);
testServer.listen(3000);

const app = express();
const httpServerPort = 23661;
app.use(cors());
app.options('*', cors());
app.use(serveStatic('dist'));
app.use(serveStatic(__dirname + '/../page'));
app.use(serveStatic('node_modules/sinon/pkg'));
app.listen(httpServerPort);

server.start();

当它运行时,它会在 Firefox 浏览器中正确运行验收测试。

我试图调用的文件

process.env.NODE_ENV

在我的最小化库调用 myLib.min.js 中。

这是未压缩文件的一部分

'use strict';

const fetch = require('isomorphic-fetch');

module.exports = id => 
  var apiUrl = 'http://liveurl.com/api/' + id;

  if (process.env.NODE_ENV === 'development') 
    apiUrl = 'http://localhost:3000/api';
  

  console.log(process.env.NODE_ENV);

    return fetch(apiUrl)
      .then(response => 
        if (response.status === 200) 
          return response.json()
            .then(myResponse => 
              var theResponse = myResponse.id;

              return theResponse;
            );
         else 
          return response.json().then(error => 
            throw new Error(error.error);
          );
        
      );
;

【问题讨论】:

【参考方案1】:

这一般通过使用environment variables来解决。

类似:

var apiUrl = 'http://localhost:3000/api'
if (process.env.NODE_ENV === 'production') 
  apiUrl = 'http://liveurl.com/api';


return fetch(apiUrl)
  .then(response => 
  //... and so on

然后您将像这样启动您的应用程序(或运行您的测试),为 NODE_ENV 填写适当的环境名称。常见值为生产|测试|开发:

NODE_ENV=production node ./path/to/app.js

【讨论】:

谢谢,所以我在 world.js 中使用命令“npm runacceptance-test”启动我的测试服务器,那么它会在 world.js 中设置 NODE_ENV 吗? 不,你会运行NODE_ENV=test npm run acceptance-test 好的,所以我的 package.json 中有 "acceptance-test": "NODE_ENV=development cucumbers"。现在,当我运行npm run acceptance-test 时,这将运行我的测试并将NODE_ENV 设置为“开发”?但是,当我在您提供的 if 语句之前将console.log(process.env.NODE_ENV) 添加到我的代码中时,它说它是undefined 嗯...这很奇怪。你能分享一下你的 package.json 和你的测试文件的要点吗? 请注意,这违背了“十二因素应用程序”所描述的普遍接受的方法。一个不太smelly 的解决方案是设置一个API_URL env var,并且只使用那里的任何东西,而不是打开NODE_ENV。 :)

以上是关于用于节点 JS 验收测试的开发 API的主要内容,如果未能解决你的问题,请参考以下文章

在验收测试中覆盖海市蜃楼响应?

如何在 Javascript 应用程序中进行冒烟测试和验收测试?

持续集成和验收测试驱动开发

Ember 验收测试不适用于 AJAX

如何在大型项目中管理用于验收测试的测试数据夹具?

验收测试 Rails 使用“测试 API”进行客户端状态控制