AngularJS サーバサイドJSONレスポンスのスタブを作成

WEBサービスを実現する場合、フロントエンドからバックエンドのAPIサーバにアクセスすることが多いと思いますが、バックエンド側がまだ開発途中であったりすると、代替としてNode.js等でスタブのアプリケーションを作ったり、または固定のJSONファイルを作ったりと、割と手間がかかってしまいます。

今回、ためしに AngularJS の ngMockE2E を利用して、擬似的なAPIサーバを構築してみたので、その方法を紹介します。

前提

  • Yeomanで構築したAngularJS開発環境が前提です。

  • 別途 ngMockライブラリをインストール場合も、Bower を使えば簡単にできます。

    • $ bower install angular-mocks

ngMockを使う準備

①index.htmlからngMockのJSファイルをロード

app/index.html
<script src="bower_components/angular-mocks/angular-mocks.js"></script>

②ルートモジュールにngMockE2Eを追加

app/scripts/app.js
'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 以降を追記してみます。
    • 面倒なのでこうしてますが、本当はファイルを分けた方がいいです。
app/scripts/app.js
'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を作って、

app/scripts/services/data.js
'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から呼び出し、

app/scripts/controllers/main.js
'use strict';

angular.module('ngMockTestApp')
  .controller('MainCtrl', ['$scope', 'JsonData', function ($scope, JsonData) {

    JsonData.getSampleData().then(function(res){

      $scope.items = res.data;

    });

  }])
;

Viewで描写します。

app/views/main.html
<!-- 対応する Controller は app.js の $routeProvider で定義済み -->
<li ng-repeat="item in items">
  {{item.id}} - {{item.name}}
</li>

結果はこんな感じ。表示されました!

スクリーンショット 2014-05-13 15.06.07.png

疑似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ファイルの生成処理がここに書けるわけです。

ほか

 

qiita.com