Angular JS + Jasmine : 객체 비교
이제 막 앵귤러 작문시험을 시작했어JS앱과 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';
};
});
Client Controller Spec:
'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)
왜 이런 일이 일어나는지 아는 사람 있나요?
또한 Angular는 처음 써보니까JS 테스트, 테스트 설정을 잘못했는지, 개선할 수 있는지에 대한 코멘트는 모두 환영합니다.
업데이트:
Client Service 포함:
'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);
});
toEqual
깊이 있는 평등을 비교합니다.즉, 오브젝트 값의 속성이 모두 같으면 오브젝트는 동일한 것으로 간주됩니다.
말씀하신 대로 어레이 내의 개체에 몇 가지 속성을 추가하는 리소스를 사용하고 있습니다.
그래서 이게{id:12}
이 상태가 되다{id:12, $then: function, $resolved: true}
동등하지 않습니다.값을 올바르게 설정했는지 테스트만 하는 경우 ID 확인은 문제 없습니다.
간단한 답변:
기존 답변에서는 모두 개체를 문자열화하거나 사용자 지정 매처/비교 함수를 만들 것을 권장합니다.단, 더 쉬운 방법이 있습니다.angular.equals()
재스민으로expect
Jasmine의 빌트인을 사용하는 대신 전화하다toEqual
매처
angular.equals()
는 Angular에 의해 객체에 추가된 추가 속성을 무시합니다.toEqual
예를 들어, 비교에 실패한다.$promise
그 물건들 중 하나에 있는 것 같아요.
자세한 설명:
내 Angular에서 같은 문제를 발견했어JS 어플리케이션시나리오를 설정합니다.
테스트에서는 로컬오브젝트와 로컬어레이를 생성하여 2개의 GET 요구에 대한 응답으로 상정했습니다.그 후 GET의 결과와 원래의 오브젝트 및 어레이를 비교했습니다.4가지 방법으로 테스트했는데 1가지 방법밖에 없었습니다.
다음은 foobar-controller-spec.js의 일부입니다.
var myFooObject = {id: 1, name: "Steve"};
var myBarsArray = [{id: 1, color: "blue"}, {id: 2, color: "green"}, {id: 3, color: "red"}];
...
beforeEach(function () {
httpBackend.expectGET('/foos/1').respond(myFooObject);
httpBackend.expectGET('/bars').respond(myBarsArray);
httpBackend.flush();
});
it('should put foo on the scope', function () {
expect(scope.foo).toEqual(myFooObject);
//Fails with the error: "Expected { id : 1, name : 'Steve', $promise : { then : Function, catch : Function, finally : Function }, $resolved : true } to equal { id : 1, name : 'Steve' }."
//Notice that the first object has extra properties...
expect(scope.foo.toString()).toEqual(myFooObject.toString());
//Passes, but invalid (see below)
expect(JSON.stringify(scope.foo)).toEqual(JSON.stringify(myFooObject));
//Fails with the error: "Expected '{"id":1,"name":"Steve","$promise":{},"$resolved":true}' to equal '{"id":1,"name":"Steve"}'."
expect(angular.equals(scope.foo, myFooObject)).toBe(true);
//Works as expected
});
it('should put bars on the scope', function () {
expect(scope.bars).toEqual(myBarsArray);
//Fails with the error: "Expected [ { id : 1, color : 'blue' }, { id : 2, color : 'green' }, { id : 3, color : 'red' } ] to equal [ { id : 1, color : 'blue' }, { id : 2, color : 'green' }, { id : 3, color : 'red' } ]."
//Notice, however, that both arrays seem identical, which was the OP's problem as well.
expect(scope.bars.toString()).toEqual(myBarsArray.toString());
//Passes, but invalid (see below)
expect(JSON.stringify(scope.bars)).toEqual(JSON.stringify(myBarsArray));
//Works as expected
expect(angular.equals(scope.bars, myBarsArray)).toBe(true);
//Works as expected
});
참고로 다음 출력은console.log
사용.JSON.stringify()
그리고..toString()
:
LOG: '***** myFooObject *****'
LOG: 'Stringified:{"id":1,"name":"Steve"}'
LOG: 'ToStringed:[object Object]'
LOG: '***** scope.foo *****'
LOG: 'Stringified:{"id":1,"name":"Steve","$promise":{},"$resolved":true}'
LOG: 'ToStringed:[object Object]'
LOG: '***** myBarsArray *****'
LOG: 'Stringified:[{"id":1,"color":"blue"},{"id":2,"color":"green"},{"id":3,"color":"red"}]'
LOG: 'ToStringed:[object Object],[object Object],[object Object]'
LOG: '***** scope.bars *****'
LOG: 'Stringified:[{"id":1,"color":"blue"},{"id":2,"color":"green"},{"id":3,"color":"red"}]'
LOG: 'ToStringed:[object Object],[object Object],[object Object]'
문자열화된 객체에 추가 속성이 있는 방법과toString
잘못된 양의 데이터를 생성합니다.
위의 내용을 참조하여 다양한 방법을 요약합니다.
expect(scope.foobar).toEqual(foobar)
: 이 동작은 양쪽 모두 실패합니다.객체를 비교할 때 toString은 Angular가 추가 속성을 추가했음을 나타냅니다.배열을 비교할 때 내용은 같아 보이지만 이 방법에서는 여전히 서로 다르다고 주장합니다.expect(scope.foo.toString()).toEqual(myFooObject.toString())
: : : : : : : : : : : : : : 。그러나 오브젝트가 완전히 변환되지 않았기 때문에 이는 잘못된 긍정입니다.이 주장은 두 개의 인수가 동일한 개체 수를 가지고 있다는 것입니다.expect(JSON.stringify(scope.foo)).toEqual(JSON.stringify(myFooObject))
: 이 메서드는 어레이를 비교할 때 적절한 응답을 제공하지만 오브젝트 비교는 raw 비교와 유사한 장애가 있습니다.expect(angular.equals(scope.foo, myFooObject)).toBe(true)
: 이것이 주장을 하는 올바른 방법입니다.Angular가 비교를 수행하도록 함으로써 백엔드에 추가된 속성을 무시하도록 인식하고 적절한 결과를 얻을 수 있습니다.
혹시라도 AngularJS 1.2.14와 Karma 0.10.10을 사용하여 팬텀에서 테스트하고 있습니다.JS 1.9.7
요약하면: 추가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]);
});
비슷한 문제가 발생하여 다음과 같은 다양한 접근방식을 사용하여 커스텀 매처를 구현했습니다.
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);
});
물론 매우 단순한 매치이기 때문에 많은 사례를 지원하지 않지만, 그보다 더 복잡한 것은 필요하지 않았습니다.구성 파일로 매처를 랩할 수 있습니다.
도 같은 그냥 요.JSON.stringify()
이치
expect( JSON.stringify( $scope.angularResource ) == JSON.stringify( expectedValue )).toBe( true );
조금 상세하게 설명하지만 예상에 실패할 경우 도움이 되는 메시지가 나타납니다.
expect(JSON.parse(angular.toJson(resource))).toEqual({ id: 1 });
설명:
angular.toJson
다음과 같은 특정 각도의 특성을 모두 제거할 수 있습니다.$promise
JSON.parse
는 JSON 문자열을 일반 오브젝트(또는 어레이)로 변환하여 다른 오브젝트(또는 어레이)와 비교할 수 있게 됩니다.
언급URL : https://stackoverflow.com/questions/15487510/angularjs-jasmine-comparing-objects
'programing' 카테고리의 다른 글
Oracle의 OVER 절 (0) | 2023.03.09 |
---|---|
AngularJS HTML5 모드 - 서버 고유의 변경 없이 다이렉트 링크는 어떻게 동작합니까? (0) | 2023.03.09 |
Wordpress 다중 사이트:서브사이트 wp-admin "err_too_many_redirects" (0) | 2023.03.09 |
woocommerce에서 제품에 대한 별 등급은 어떻게 추가합니까? (0) | 2023.03.09 |
JavaScript 변수를 PHP 변수로 보내기 (0) | 2023.03.09 |