44

AngularJS アプリのテストを書き始めたばかりで、Jasmine で行っています。

関連するコードスニペットは次のとおりです

クライアントコントローラー:

'use strict';

adminConsoleApp.controller('ClientController',
    function ClientController($scope, Client) {

        //Get list of clients
        $scope.clients = Client.query(function () {
            //preselect first client in array
            $scope.selected.client = $scope.clients[0];
        });

        //necessary for data-binding so that it is accessible in child scopes.
        $scope.selected = {};

        //Current page
        $scope.currentPage = 'start.html';

        //For Client nav bar
        $scope.clientNavItems = [
            {destination: 'features.html', title: 'Features'},
        ];

        //Set current page
        $scope.setCurrent = function (title, destination) {
            if (destination !== '') {
                $scope.currentPage = destination;
            }

        };

        //Return path to current page
        $scope.getCurrent = function () {
            return 'partials/clients/' + $scope.currentPage;
        };

        //For nav bar highlighting of active page
        $scope.isActive = function (destination) {
            return $scope.currentPage === destination ? true : false;
        };

        //Reset current page on client change
        $scope.clientChange = function () {
            $scope.currentPage = 'start.html';
        };
    });

ClientControllerSpec:

'use strict';

var RESPONSE = [
    {
        "id": 10,
        "name": "Client Plus",
        "ref": "client-plus"
    },
    {
        "id": 13,
        "name": "Client Minus",
        "ref": "client-minus"
    },
    {
        "id": 23805,
        "name": "Shaun QA",
        "ref": "saqa"
    }
];

describe('ClientController', function() {

    var scope;

    beforeEach(inject(function($controller, $httpBackend, $rootScope) {
        scope = $rootScope;
        $httpBackend.whenGET('http://localhost:3001/clients').respond(RESPONSE);
        $controller('ClientController', {$scope: scope});
        $httpBackend.flush();
    }));

    it('should preselect first client in array', function() {
        //this fails.
        expect(scope.selected.client).toEqual(RESPONSE[0]);
    });

    it('should set current page to start.html', function() {
        expect(scope.currentPage).toEqual('start.html');
    });
});

テストは失敗します:

Chrome 25.0 (Mac) ClientController should preselect first client in array FAILED
    Expected { id : 10, name : 'Client Plus', ref : 'client-plus' } to equal { id : 10, name : 'Client Plus', ref : 'client-plus' }.
    Error: Expected { id : 10, name : 'Client Plus', ref : 'client-plus' } to equal { id : 10, name : 'Client Plus', ref : 'client-plus' }.
        at null.<anonymous> (/Users/shaun/sandbox/zong-admin-console-app/test/unit/controllers/ClientControllerSpec.js:43:39) 

なぜこれが起こっているのかについて誰か考えがありますか?

また、私は AngularJS テストを作成するのが初めてなので、テストの設定が間違っているかどうか、またはテストを改善できるかどうかについてのコメントを歓迎します。

アップデート:

ClientService を含む:

'use strict';

AdminConsoleApp.services.factory('Client', function ($resource) {
    //API is set up such that if clientId is passed in, will retrieve client by clientId, else retrieve all.
    return $resource('http://localhost:port/clients/:clientId', {port: ':3001', clientId: '@clientId'}, {

    });
});

また、代わりに ID を比較することで問題を回避しました。

it('should preselect first client in array', function () {
    expect(scope.selected.client.id).toEqual(RESPONSE[0].id);
});
4

6 に答える 6

69

toEqual深い平等の比較を行います。つまり、オブジェクトの値のすべてのプロパティが等しい場合、オブジェクトは等しいと見なされます。

あなたが言ったように、あなたは配列内のオブジェクトにいくつかのプロパティを追加するリソースを使用しています。

だからこれは等しくないこれに{id:12}なります。{id:12, $then: function, $resolved: true}値を適切に設定したかどうかをテストするだけであれば、IDチェックは問題ないはずです。

于 2013-03-18T23:35:59.640 に答える
14

angular.equals簡単に言うと、ジャスミンマッチャーとして追加します。

beforeEach(function(){
  this.addMatchers({
    toEqualData: function(expected) {
      return angular.equals(this.actual, expected);
    }
  });
});

したがって、次のように使用できます。

it('should preselect first client in array', function() {
    //this passes:
    expect(scope.selected.client).toEqualData(RESPONSE[0]);

    //this fails:
    expect(scope.selected.client).toEqual(RESPONSE[0]);
});
于 2014-10-15T14:19:22.783 に答える
7

同様の問題が発生し、多くのアプローチに基づいて、次のようにカスタム マッチャーを実装しました。

beforeEach(function() {
  this.addMatchers({
    toBeSimilarTo: function(expected) {
      function buildObject(object) {
        var built = {};
        for (var name in object) {
          if (object.hasOwnProperty(name)) {
            built[name] = object[name];
          }
        }
        return built;
      }

      var actualObject = buildObject(this.actual);
      var expectedObject = buildObject(expected);
      var notText = this.isNot ? " not" : "";

      this.message = function () {
        return "Expected " + actualObject + notText + " to be similar to " + expectedObject;
      }

      return jasmine.getEnv().equals_(actualObject, expectedObject);

    }
  });
});

そして、このように使用しました:

it("gets the right data", function() {
  expect(scope.jobs[0]).toBeSimilarTo(myJob);
});

もちろん、これは非常に単純なマッチャーであり、多くのケースをサポートしていませんが、それ以上複雑なものは必要ありませんでした。構成ファイルでマッチャーをラップできます。

同様の実装については、この回答を確認してください。

于 2013-05-28T19:00:29.000 に答える
2

私は同じ問題を抱えていたので、JSON.stringify()比較するオブジェクトを呼び出しました。

expect( JSON.stringify( $scope.angularResource ) == JSON.stringify( expectedValue )).toBe( true );
于 2014-05-06T06:01:17.573 に答える