11

我正在使用 Yeoman、Grunt 和 Bower 来构建一个平台,用于构建独立于后端的前端。我的想法是我的所有(AngularJS)控制器、服务、工厂等都存在于这个项目中,然后根据 grunt 构建的结果注入到我的服务器端代码库中。

我的问题是:

如何模拟端点,以便 Grunt 服务器响应与我的(Rails)应用程序相同的端点?

目前我正在使用:

 angular.module('myApp', ['ngResource'])

 .run(['$rootScope', function ($rootScope) {
     $rootScope.testState = 'test';
  }]);

然后在我的每一项个人服务中:

   mockJSON = {'foo': 'myMockJSON'}

在每种方法上:

   if($rootScope.testState == 'test'){
    return mockJSON;
  }
  else {
    real service logic with $q/$http goes here
  }

然后之后grunt buildtestState = 'test'被删除。

这显然是一个相对笨拙的架构。我怎样才能避免它?如何让 Grunt 响应与我的应用程序相同的端点(其中一些具有动态参数)应用一些逻辑(如果需要),并提供一个 json 文件(可能取决于路径参数)?

4

6 回答 6

14

我已经通过使用 express 编写一个使用静态 json 响应的服务器来解决这个问题。

首先,我在我的项目中创建了一个名为“api”的目录。在该目录中,我有以下文件:

package.json

   {
     "name": "mockAPI",
     "version": "0.0.0",
     "dependencies": {
        "express": "~3.3.4"
      }
   }

然后我npm install在这个目录中运行。

index.js

    module.exports = require('./lib/server');

lib/server.js

    express = require('express');
    var app = express();

    app.get('/my/endpoint', function(req, res){
        res.json({'foo': 'myMockJSON'});
   });

    module.exports = app

最后在我的全球Gruntfile.js

         connect: {
            options: {
               port: 9000,
               hostname: 'localhost',
            },
            livereload: {
              options: {
                 middleware: function (connect, options) {
                   return [
                     lrSnippet,
                     mountFolder(connect, '.tmp'),
                     mountFolder(connect, yeomanConfig.app),
                     require('./api')
                   ];
               }
            }
         },

然后服务发出请求,快递服务器提供正确的 JSON。

之后grunt build,express 服务器被一个 rails 服务器简单地替换。

于 2013-07-31T03:52:47.110 回答
8

grunt-contrib-connectv.0.7.0 开始,您还可以将自定义中间件添加到现有中间件堆栈中,而无需手动重建现有中间件堆栈。

livereload: {
    options: {
        open: true,
        base: [
            '.tmp',
            '<%= config.app %>'
        ],
        middleware: function(connect, options, middlewares) {
            // inject a custom middleware into the array of default middlewares
            middlewares.push(function(req, res, next) {
                if (req.url !== '/my/endpoint') {
                    return next();
                }
                res.writeHead(200, {'Content-Type': 'application/json' });
                res.end("{'foo': 'myMockJSON'}");
            });
            return middlewares;
        }
    }
},

有关官方文档,请参见https://github.com/gruntjs/grunt-contrib-connect#middleware

于 2014-03-17T18:53:43.617 回答
4

或者,您可以使用grunt-connect-proxy将测试服务器中缺少的所有内容代理到实际后端。

它很容易安装,在将代理添加到 livereload 连接中间件时要记住的一件事是最后添加它,如下所示:

middleware: function (connect) {
    return [
        lrSnippet,
        mountFolder(connect, '.tmp'),
        mountFolder(connect, yeomanConfig.app),
        proxySnippet
    ];
}
于 2013-08-02T18:43:46.523 回答
2

grunt-connect-prism类似于 Ruby 项目VCR。它为前端开发人员提供了一种简单的方法来记录他们的 API(或其他一些远程源)返回的 HTTP 响应并在以后重放它们。它基本上是一个 HTTP 缓存,但适用于开发单页应用程序 (SPA) 的开发人员。 您还可以为不存在的 API 调用生成存根,并以您想要的方式填充它们。

它对于在开发过程中模拟复杂和高延迟的 API 调用很有用。在仅为您的 SPA 编写 e2e 测试时,它也很有用,从等式中删除服务器。这可以更快地执行您的 e2e 测试套件。

Prism 通过向grunt-contrib-connect插件提供的连接服务器添加自定义连接中间件来工作。在“记录”模式下,它将在文件系统上为每个响应生成一个文件,内容如下:

  {
    "requestUrl": "/api/ponies",
    "contentType": "application/json",
    "statusCode": 200,
    "data": {
      "text": "my little ponies"
    }
  }

免责声明:我是这个项目的作者。

于 2014-09-07T20:27:16.713 回答
0

您可以使用 Apache 代理并将您的 REST 服务器与 gruntjs 连接。

Apache 会这样做:代理 / -> gruntjs 代理 /service -> REST 服务器


你会使用你的应用程序来访问 Apache,而 angular.js 应用程序会认为它正在与自己对话,所以没有跨域问题。

这是一个关于如何设置的很棒的教程:http: //alfrescoblog.com/2014/06/14/angular-js-activiti-webapp-with-activiti-rest/

于 2014-06-15T10:03:19.793 回答
0

只是我基于亚伯拉罕 P 的回答的另一种方式。它不需要在“api”文件夹中安装 express。我可以为某些文件分离模拟服务。例如,我的 'api' 文件夹包含 3 个文件:

接口\

  • index.js // 分配所有“模块”,然后简单地要求它。
  • user.js // 全部为用户模拟
  • product.js // 对产品的所有模拟

文件user.js

var user = function(req, res, next) {
if (req.method === 'POST' && req.url.indexOf('/user') === 0) {
     res.end(
          JSON.stringify({
                    'id' : '5463c277-87c4-4f1d-8f95-7d895304de12',
                    'role' : 'admin'
            })
         );
    }
    else {
        next();
    }
}
module.exports = user;

文件product.js

var product = function(req, res, next) {
if (req.method === 'POST' && req.url.indexOf('/product') === 0) {
     res.end(
          JSON.stringify({
                    'id' : '5463c277-87c4-4f1d-8f95-7d895304de12',
                    'name' : 'test',
                    'category': 'test'
            })
         );
    }
    else {
        next();
    }
}
module.exports = product;

index.js 只是分配所有的“模块”,我们只需要它。

module.exports = {
    product: require('./product.js'),
    user: require('./user.js')
};

我的Gruntfile.js文件

 connect: {
      options: {
        port: 9000,
        // Change this to '0.0.0.0' to access the server from outside.
        hostname: 'localhost',
        livereload: 35729
      },
      livereload: {
        options: {
          open: true,
          middleware: function (connect) {

            return [
              connect.static('.tmp'),
              connect().use(
                '/bower_components',
                connect.static('./bower_components')
              ),
              connect.static(appConfig.app),
              require('./api').user,
              require('./api').product,
            ];
          }
        }
      }
于 2016-04-12T14:17:21.370 回答