使用promises测试服务的AngularJS / Jasmine unittest有什么问题?

时间:2014-01-13 14:47:30

标签: angularjs jasmine

现在试图绕着这个角度模拟茉莉花测试我的头几天了。有一些基本的东西在工作但是当想要间谍并在模拟上断言时我会卡住。

测试代码

describe("My service tests: calls correct urls and resolves", function () {
var $myService, $httpBackend, $q, deffered;
beforeEach(module('myModule', function ($provide) {
    var mockEndpointService = {
        getApiEndpoint: function () {
            return 'mockEndPoint';
        }
    };

    $provide.value('$endpointService', mockEndpointService);
}));
beforeEach(inject(function (_$myService_) {
    $myService= _myService_;
}));
beforeEach(inject(function ($injector) {
    $httpBackend = $injector.get('$httpBackend');
    $q = $injector.get('$q');

    deffered = $q.defer();
    spyOn($q, 'defer').andReturn(deffered);
    spyOn(deffered, 'resolve');
    $httpBackend.when('GET', 'mockEndPoint/testtest').respond(123);
}));

it("Get calls correct URL and resolves deffered on success", function () {
    $myService.get('testtest');
    $httpBackend.expect('GET', 'mockEndPoint/testtest');
    $httpBackend.flush(); //Added this
    expect(deffered.resolve).toHaveBeenCalledWith(123); //This assert fails
});
});

服务代码

myModule.factory('$myModule', ['$http', '$q', '$endpointService',     function ($http, $q, $endpointService) {
var apiPath = $endpointService.getApiEndpoint('MyApi');
this.get = function (id) {
    var deferred = $q.defer();
    var url = apiPath + '/' + id;
    console.log('GET: ' + url);
    $http.get(url).success(function (data) {
        deferred.resolve(data);
    }).error(function () {
        deferred.reject('error: could not load thingy with id: ' + id);
    });

    return deferred.promise;
};

}]);

所以问题一,我有3个之前的每个块,我可以合并其中一些吗?当我尝试这样做时,我会遇到各种各样的错误。

此外,我将如何断言已解决的是在get的成功调用? 你看到我在上面尝试了什么,但它不起作用。

提前谢谢。

编辑: 添加刷新似乎有所不同,但不是预期的结果,所以任何关于承诺和延期的帮助都非常感谢。

EDIT2: 改变标题实际上反映了我遇到的问题。

// TWD

1 个答案:

答案 0 :(得分:4)

从上一个$httpBackend.when块中删除beforeEach,测试应如下所示:

it("Get calls correct URL and resolves deffered on success", function () {
    $httpBackend.expect('GET', 'mockEndPoint/testtest').respond(123);
    $myService.get('testtest');
    $httpBackend.flush();
    expect(deffered.resolve).toHaveBeenCalledWith(123);
});
必须调用

$httpBackend.flush来解决$http.get的承诺。只有在那之后,才会调用deferred对象的解析。

<强>更新

我认为开始监视供应商功能是一个坏主意,这是您在单元测试代码时要做的最后一件事。而且,在您的服务代码中,没有必要创建一个新的延迟对象,因为$http.get将向您返回一个承诺,因此您可以简化代码,如下所示:

this.get = function (id) {
    var url = apiPath + '/' + id;
    console.log('GET: ' + url);

    return $http.get(url).success(function (data) {
        return data;
    }).error(function () {
        return 'error: could not load thingy with id: ' + id;
    });
};

现在,您可以像这样测试:

it("Get calls correct URL and resolves deffered on success", function () {
    $httpBackend.expect('GET', 'mockEndPoint/testtest').respond(123);

    $myService.get('testtest').then(function(data) {
        expect(data).toEqual(123);
    });

    $httpBackend.flush();
});