Использование Grunt to Mock Endpoints
Я использую 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 build
удаляется testState = 'test'
.
Это явно относительно сумасшедшая архитектура. Как я могу избежать этого? Как я могу заставить Grunt отвечать на те же конечные точки, что и мое приложение (некоторые из которых имеют динамические параметры) применяют некоторую логику (если необходимо) и служат для json файла (возможно, зависящего от параметров пути)?
Ответы
Ответ 1
Я исправил эту проблему, используя экспресс, чтобы написать сервер, который отвечает статическим 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
, экспресс-сервер просто заменяется сервером rails.
Ответ 2
Начиная с grunt-contrib-connect
v.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 для официальной документации.
Ответ 3
В качестве альтернативы вы можете использовать grunt-connect-proxy, чтобы проксировать все, что отсутствует на вашем тестовом сервере, на фактический сервер.
Это довольно просто установить, только одна вещь, которую нужно помнить при добавлении прокси-сервера к промежуточному программному обеспечению, связанному с пересылкой в реестре, - это добавить его последним, например:
middleware: function (connect) {
return [
lrSnippet,
mountFolder(connect, '.tmp'),
mountFolder(connect, yeomanConfig.app),
proxySnippet
];
}
Ответ 4
grunt-connect-prism аналогичен проекту Ruby VCR. Он предоставляет простой способ для разработчиков переднего плана записывать ответы HTTP, возвращаемые их API (или другим удаленным исходным кодом), и воспроизводить их позже. Это, в основном, кеш HTTP, но для разработчиков, работающих с одним страничным приложением (SPA). Вы также можете создавать заглушки для вызовов API, которые не существуют, и заполнять их так, как вы хотите.
Он полезен для издевательства сложных вызовов API с высокой задержкой во время разработки. Это также полезно при написании тестов e2e только для вашего SPA, удаление сервера из уравнения. Это приводит к значительно более быстрому выполнению вашего тестового пакета e2e.
Призма работает, добавляя настраиваемое связующее ПО для подключения к серверу подключения, предоставляемого плагином grunt-contrib-connect. В режиме "записи" он будет генерировать файл за ответ в файловой системе с содержимым следующего содержания:
{
"requestUrl": "/api/ponies",
"contentType": "application/json",
"statusCode": 200,
"data": {
"text": "my little ponies"
}
}
ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: Я являюсь автором этого проекта.
Ответ 5
Вы можете использовать прокси-сервер Apache и подключить сервер REST с помощью gruntjs.
Apache сделает следующее:
прокси /- > gruntjs
proxy/service → сервер REST
вы использовали бы приложение, попавшее в Apache, и приложение angular.js подумало бы, что разговаривает с самим собой, поэтому проблема с перекрестным доменом отсутствует.
Вот отличный учебник по настройке:
http://alfrescoblog.com/2014/06/14/angular-js-activiti-webapp-with-activiti-rest/
Ответ 6
Взгляните на swagger-api-mock, который отлично сочетается с rest-json.
Ответ 7
Просто мой альтернативный способ, основанный на ответе Авраама Р. Это не нужно устанавливать экспресс в папке "api". Я могу отделить макетные сервисы для определенных файлов. Например, моя папка "api" содержит 3 файла:
апи\
- index.js//присваиваем все "модули", а затем просто требуем этого.
- user.js//все насмешливые для пользователя
- product.js//все насмехающиеся за продукт
file 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;
file 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,
];
}
}
}