WEBサービスを実現する場合、フロントエンドからバックエンドのAPIサーバにアクセスすることが多いと思いますが、バックエンド側がまだ開発途中であったりすると、代替としてNode.js等でスタブのアプリケーションを作ったり、または固定のJSONファイルを作ったりと、割と手間がかかってしまいます。
今回、ためしに AngularJS の ngMockE2E を利用して、擬似的なAPIサーバを構築してみたので、その方法を紹介します。
前提
-
Yeomanで構築したAngularJS開発環境が前提です。
-
$ yo angular --minsafe
-
そうすると、次のように ngMockライブラリが最初から入ってます。
-
-
別途 ngMockライブラリをインストール場合も、Bower を使えば簡単にできます。
$ bower install angular-mocks
ngMockを使う準備
①index.htmlからngMockのJSファイルをロード
<script src="bower_components/angular-mocks/angular-mocks.js"></script>
②ルートモジュールにngMockE2E
を追加
'use strict';
angular.module('ngMockTestApp', [
'ngCookies',
'ngResource',
'ngSanitize',
'ngRoute',
+ 'ngMockE2E'
])
.config(['$routeProvider', function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/main.html',
controller: 'MainCtrl'
})
.otherwise({
redirectTo: '/'
});
}]);
これで準備は完了です。
疑似APIサーバの処理を書く
- 先程と同じ
app.js
に、.run
以降を追記してみます。- 面倒なのでこうしてますが、本当はファイルを分けた方がいいです。
'use strict';
angular.module('ngMockTestApp', [
'ngCookies',
'ngResource',
'ngSanitize',
'ngRoute',
'ngMockE2E'
])
.config(['$routeProvider', function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/main.html',
controller: 'MainCtrl'
})
.otherwise({
redirectTo: '/'
});
}])
.run(['$httpBackend', function ($httpBackend) {
$httpBackend.whenGET(/^views\//).passThrough();
var sample = [
{
"id": "1",
"name": "山田"
},
{
"id": "2",
"name": "鈴木"
}
];
$httpBackend.whenGET('data/sample.json?hoge=1').respond(200, sample, {});
$httpBackend.whenGET('data/sample.json?hoge=2').respond(function(method, url, data, headers) {
return [200, sample, {}];
});
}])
;
動作確認
ここは何でもいいのですが、APIを叩く処理を書きます。
まず、APIにアクセスするFactoryを作って、
'use strict';
angular.module('ngMockTestApp')
.factory('JsonData', function ($http) {
return {
getSampleData: function () {
return $http.get('data/sample.json?hoge=1')
.success(function(data, status, headers, config) {
return data;
});
}
}
})
;
Controllerから呼び出し、
'use strict';
angular.module('ngMockTestApp')
.controller('MainCtrl', ['$scope', 'JsonData', function ($scope, JsonData) {
JsonData.getSampleData().then(function(res){
$scope.items = res.data;
});
}])
;
Viewで描写します。
<!-- 対応する Controller は app.js の $routeProvider で定義済み -->
<li ng-repeat="item in items">
{{item.id}} - {{item.name}}
</li>
結果はこんな感じ。表示されました!
疑似APIサーバの処理をみてみる
.run(['$httpBackend', function ($httpBackend) {
$httpBackend.whenGET(/^views\//).passThrough();
var sample = [
{
"id": "1",
"name": "山田"
},
{
"id": "2",
"name": "鈴木"
}
];
$httpBackend.whenGET('data/sample.json?hoge=1').respond(200, sample, {});
$httpBackend.whenGET('data/sample.json?hoge=2').respond(function(method, url, data, headers) {
return [200, sample, {}];
});
}])
全ての HTTPアクセスがこのロジックを経由します。
で、ここに全てのHTTPアクセスについて定義しないとエラーになるので、注意が必要です。
(正規表現はつかえます。)
.passThrough()
は何もしない、という意味です。テンプレートのアクセスもHTTP経由なので、「URLが views/
で始まる場合は何もしない」というふうに記載しています。
whenGET
でURLを定義し、対応するレスポンスを .respond
に記載します。今回は2パターンを記載してみました。
上のパターンは、単純に用意されたJSONデータをレスポンンスしています。
下のパターンは、JavaScriptでいろいろ処理させてからレスポンンスさせるパターンです。
この例だと、結局JSONをレスポンスしているだけですが、判定処理とか動的なJSONファイルの生成処理がここに書けるわけです。
ほか
-
詳しくは AngularJS のドキュメントをご覧ください。
-
今回つくったソースはGitHubにおいてあります。