繁体   English   中英

在Angular服务中进行$ q承诺的单元测试-Karma,Jasmine

[英]Unit testing $q promise within Angular service - Karma, Jasmine

我正在尝试与Karma和Jasmine一起对Angular服务进行单元测试。 我正在看过许多有关如何对来自控制器的服务调用进行单元测试的教程,但是我希望对服务本身进行单元测试。 UsersService.findById()进行异步调用以在ID中查找ID,但是我不知道如何编写通过测试。 我已经接近了,但是我需要一点帮助。 这是UsersService中的函数

users.service.js

        Users.findById = function(id){
            var deferred = $q.defer();

            deferred.resolve(userList.find(function(user){
                return user.id == id;
            }));

            return deferred.promise;
        };

规格如下:

users.service.spec.js

describe("Users Factory", function(){
    var UsersService, $q, $rootScope, $provide, deferred, mockedDeferred;

    var userList = [
        { id: 1, name: "Richard Hendricks", email: "richard@piedpiper.com", phone: 4085550011, pokemon: { isPresent: true, name: "eevee"}, icon: { isPresent: false, name: null} },
        { id: 2, name: "Erlich Bachman", email: "erlich@aviato.com", phone: 4155552233, pokemon: { isPresent: true, name: "celebi"}, icon: { isPresent: false, name: null} },
        { id: 3, name: "Gavin Belson", email: "gavin@hooli.com", phone: 9165554455, pokemon: { isPresent: true, name: "snorlax"}, icon: { isPresent: false, name: null} }
    ];

    var singleUser = { id: 2, name: "Erlich Bachman", email: "erlich@aviato.com", phone: 4155552233, pokemon: { isPresent: true, name: "celebi"}, icon: { isPresent: false, name: null} };

    function mockQ(){
        deferred = $q.defer();
        spyOn(UsersService, "findById");
        return deferred;
    }

    beforeEach(angular.mock.module("testing_app"));
    beforeEach(angular.mock.module(function(_$provide_){
        $provide = _$provide_;
    }));

    beforeEach(inject(function(_UsersService_, _$q_, _$rootScope_){
        UsersService = _UsersService_;
        $q = _$q_;
        $rootScope = _$rootScope_;
    }));

    describe("Users.findById()", function(){

        beforeEach(function(){
            mockedDeferred = mockQ();
        });

        it("should exist", function(){
            expect(UsersService.findById).toBeDefined();
        });

        it("should equal singleUser", function(){
            UsersService.findById(2);
            deferred.resolve(userList.find(function(user){
                return user.id == 2;
            }));
            expect(UsersService.findById).toHaveBeenCalled();
            expect(deferred.promise).toEqual(singleUser);
        });
    });
});

这是控制台中的内容:

埃利希·巴赫曼,这是你妈妈。你不是我的宝贝

我接近了,但是如何获得等于singleUser变量的承诺?

您正在测试UsersService服务。 因此,您的测试用例应使用该服务并验证其行为是否正确。 考虑到这一点,检查是否在调用它的同一个函数(测试)上调用了findById()不会提供任何验证,并且是多余且不必要的。 在这个特定的测试用例中,更有效的检查将是验证该方法是否返回类似Promise的对象(有关更多信息,请参见此处 )。 另一个有效的检查将是验证已知输入方法的响应值(一旦解决了诺言)。 对于后者,您需要执行的是$rootScope.$apply(); 在对照期望的承诺检查解决的价值之前(请参阅angularjs文档中关于promise测试部分,以了解该示例)。 一旦应用了此建议,对findById()的测试将如下所示:

describe("Users.findById()", function(){

    it("should exist", function(){
        expect(UsersService.findById).toBeDefined();
    });

    it("should produce a promise", function(){
        var p = UsersService.findById(2);

        expect(p instanceof $q.resolve().constructor).toBeTruthy();
    });

    it("should equal singleUser", function(){
        var p = UsersService.findById(2), resolvedValue;

        p.then(function(value) { resolvedValue = value; });

        $rootScope.$apply();

        expect(resolvedValue).toEqual(singleUser);
    });
});

在某些情况下,被测服务更为复杂,并封装了其他低层服务。 在这些情况下,您需要监视或模拟那些较低级别的服务,以便通过检查被调用的较低级别服务来验证被测较高级别服务的行为是否符合预期。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM