使用params对AngularJs$资源查询进行单元测试

Unit test AngularJs $resource query with params

本文关键字:查询 单元测试 资源 params AngularJs 使用      更新时间:2023-09-26

我想知道如何使用params对AngularJs$资源查询进行单元测试。

我有这个:

services.js

angular.module('conciergeApp.services', ['ngResource'])
    .factory('Reply', function($resource) {
        return $resource('/api/reply/:id/');
    });

controllers.js

conciergeControllers.controller('ReplyCtrl', ['$scope', 'Reply',
    function($scope, Reply) {
        $scope.hotel_replies = Reply.query({
            hotel: $scope.hotel_id
        });
    }
]);

因此,这里查询的API端点是:

'/api/reply/?hotel=<hotel_id>'
// aka
'/api/reply/?hotel=1'

这在手动测试时是有效的,但你如何对其进行单元测试?

使用Jasmine spyOn$httpBackend。哪一个好?

这个可以用吗?我尝试过这种模式,但没能成功:

spyOn(object, 'method').andCallFake(function({foo:bar}) {
  return myMockObject
});

此处使用Jasmine 2.0和htmlRunner的示例。解释如下:

因此,在您的ReplyCtrl单元测试中:

describe('ReplyCtrl Controller', function () {
    var Reply;
    var ReplyCtrl;
    var $scope;
    var ReplyQueryMock;
    var HOTEL_ID = 1234;
    beforeEach(module('conciergeApp'));
    beforeEach(inject(function (_Reply_, $controller, $rootScope) {
        // This object can be used throughout your controller unit test for the
        // response of calling the Reply.query method
        ReplyQueryMock = {};
        Reply = _Reply_;
        spyOn(Reply, 'query').and.returnValue(ReplyQueryMock);
        $scope = $rootScope.$new();
        $scope.hotel_id = HOTEL_ID;
        ReplyCtrl = $controller('ReplyCtrl', {$scope: $scope});
    }));
    it('should populate hotel_replies', function () {
        expect(Reply.query).toHaveBeenCalledWith({
            hotel: HOTEL_ID
        });
        expect($scope.hotel_replies).toBe(ReplyQueryMock);
    });
});

这将模拟您的Reply服务,并为查询返回一个模拟对象。您将验证$scope的hotel_replies是使用$scope上存在的hotel_id调用Reply.query的结果。

编辑:大概$resource已经为您进行了单元测试(由Angular团队!)。您可能只想验证您是否使用正确的URL设置了资源,而不是深入了解$resource的真正功能(例如调用$http)。上面的Fiddle链接更新了,看起来如下:

describe('Reply Resource', function () {
    var Reply;
    var $resource;
    var ReplyResourceMock;
    beforeEach(module('conciergeApp.services', function ($provide) {
        // Mock out $resource here
        $provide.factory('$resource', function () {
            ReplyResourceMock = {};
            var $resource = jasmine.createSpy('$resource');
            $resource.and.returnValue(ReplyResourceMock);
            return $resource;
        });
    }));
    beforeEach(inject(function (_Reply_, _$resource_) {
        Reply = _Reply_;
        $resource = _$resource_;
    }));
    it('should initialize resource', function () {
        expect($resource).toHaveBeenCalledWith('/api/reply/:id/');
        expect(Reply).toBe(ReplyResourceMock);
    });
});

从最初的答案来看,可能有些过头了,因为你使用$resource来抽象$http(仍然显示在fiddle中)

然后,为了验证$resource在回复工厂/服务中是否正常工作,您需要注入$httpBackend。您可以验证是否使用正确的数据调用了正确的REST端点