Jasmine没有解决角度承诺

时间:2016-11-18 10:33:18

标签: javascript angularjs jasmine karma-jasmine

我是Jasmine的新手。我试图让我的工厂承诺解决,但它似乎永远不会。

这是我的工厂,它将重新列出公司名单

angular.module('commercial.factories').factory('companyFactory', companyFactory);

function companyFactory($http, $location, sessionStorage, config) {
    function getCompanies() {
        //call service and include company identifier in the service url
        return $http.get(wunUtils.constants.serviceBaseUrl + 'myCompanyService.svc/companies')
            .then(function(response) {
                return response.data;
            }, function(err){
                console.log(err);
            });
    }
});

和我的规范

describe('company', function() {
beforeEach(module('mockedCommercial'));

var $httpBackend, companyFactory, $rootScope

beforeEach(function() {

    inject(function(_$httpBackend_, _$rootScope_, _companyFactory_) {
        $rootScope = _$rootScope_;
        $httpBackend = _$httpBackend_;
        companyFactory = _companyFactory_;
    });
})


it('should return available languages asynchronously', function() {


    $httpBackend.expectGET(/https:\/\/myDomain.com\/myCompanyService.svc\/companies+/)

        .respond(function(method, url, data, headers, params) {

            var response = {
                "data": [{
                    "address1": "Portsmouth",
                    "address2": null,
                    "city": "Portsmouth",
                    "contactEmail": "mocks@mocks.com",
                    "contactFirstName": "Mock",
                    "contactLastName": "Data",
                    "contactPhone": null,
                    "contactTitle": "Mr",
                    "country": "UK",
                    "fax": null,
                    "identifier": "c1xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
                    "location": "Portsmouth, UK",
                    "name": "Mock Company 1",
                    "phone": null,
                    "state": "Hampshire",
                    "zipCode": "PO19 3 EN"
                }, {
                    "address1": "Portsmouth",
                    "address2": null,
                    "city": "Portsmouth",
                    "contactEmail": "mocks@mocks.com",
                    "contactFirstName": "Test",
                    "contactLastName": "Test",
                    "contactPhone": null,
                    "contactTitle": "Mrs",
                    "country": "UK",
                    "fax": null,
                    "identifier": "c2xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
                    "location": "Portsmouth, UK",
                    "name": "Mock Company 2",
                    "phone": null,
                    "state": "Hampshire",
                    "zipCode": "Po9 3EN"
                }],
                "total": 2
            }

        });


    //--------------------------

    $rootScope.$digest();

    companyFactory.GetCompanies().then(function(result) {
        expect(result.hasOwnProperty('total')).toBe(true);
    })
});
});

正如你所看到的,我正在使用$ rootScope。$ digest运行承诺,但是我的期望从未被击中,所以测试总是通过。

我已阅读大量关于此事的不同帖子,他们都说这应该有效。我在这里做错了什么还是我错过了一些步骤?

已编辑 - 简化方法

所以我在看了一些更多的帖子后稍微简化了我的问题

这是我的新控制器电话......

        $scope.companies = [];
    var GetCompanies = function(options) {
        companyFactory.GetCompanies().then(function(response) {
            options.success(response);
            $scope.companies = response
        });
    }
$scope.GetCompanies = GetCompanies

我的工厂......

function getCompanies() {
    //call service and include company identifier in the service url
    return $http.get(wunUtils.constants.serviceBaseUrl + 'CompanyService.svc/companies')
        .then(function(response) {
            return response.data;
        }, function(err){
            console.log(err);
        });
}
    var service = {
    AddCompany: addCompany,
    GetCompany: getCompany,
    GetCompanies: getCompanies,
    GetUserCompanyFleets: getUserCompanyFleets,
    EditCompany: editCompany
};

和我的新规格

describe('company', function() {
beforeEach(module('mockedCommercial'));

var $httpBackend, companyFactory, $rootScope, createController, scope

beforeEach(function() {

    inject(function($controller, _$httpBackend_, _$rootScope_, _companyFactory_) {
        $rootScope = _$rootScope_;
        $httpBackend = _$httpBackend_;
        scope = _$rootScope_.$new();
        companyFactory = _companyFactory_;
        createController = function() {
            return $controller('ManageCompaniesController', {
                '$scope': scope
            });
        };
    });
})


it('should return available languages asynchronously', function(done) {

    $httpBackend.whenGET(/https:\/\/myDomain.com\/V3_Fleet\/CompanyService.svc\/companies+/)

        .respond(function(method, url, data, headers, params) {
                return [{ 'id': 1 }];
            }
        });

    //--------------------------
    var dummy = [{ 'id': 1 }];

    createController();

    scope.GetCompanies()

    $httpBackend.flush()


    expect(scope.companies).toEqual(dummy)


    scope.$digest(); done()

});

});

3 个答案:

答案 0 :(得分:0)

在评估测试期望之前尝试使用$httpBackend.flush()

这是angular推荐的方法。有关更多详细信息和示例,请查看documentation here

答案 1 :(得分:0)

测试异步代码时有两种选择。

1。使用同步模拟

这包括:

  • mock $httpBackend
  • 使用$timeout.flush()
  • 使用$interval.flush()
  • 使用scope.$apply()处理剩余的承诺

在所有这些之后,你仍然不能完全确定所有待处理的任务都已经处理完毕,尽管它在99.9%的时间内已经足够了。

2。使您的测试异步

在这里,您必须确保每个异步控制器方法都返回一个promise,即使返回的promise未在应用程序中使用。它们将用于测试。

Jasmine使异步测试非常困难,但并非不可能。您必须使用done callback,并对每个异步块进行编码,如:

it('should...', function(done) {
    $q.when().then(function() {
        return $controller.GetSomething();
    }).then(function() {
        expect(scope.companies).toEqual(dummy);
    }).then(done, done.fail);
});

Mocha handles proper asynchronous functions所以你可以不用done写一下:

it('should...', function() {
    return $q.when().then(function() {
        return $controller.GetSomething();
    }).then(function() {
        expect(scope.companies).toEqual(dummy);
    });
});

如果你有工具集,甚至可以使用async-await

it('should...', async () => {
    await $controller.GetSomething();
    expect(scope.companies).toEqual(dummy);
});

答案 2 :(得分:0)

所以经过多次阅读后,我通过简化一切来找到答案。我认为我的问题来自混合 $ httpBackend.flush()完成()功能

似乎发生的事情是done()函数触发了自己的摘要,因此在尝试使用flush()函数时会发生冲突。

这是我的工厂。它与我原来的有点不同,因为这是一个更简单的功能(更少的东西出错)

        function getUser(userId) {
        //call service and include user identifier in the service url
        return $http.get(wunUtils.constants.serviceBaseUrl + 'myService.svc/fleetusers/' + userId)
            .then(function(response) {
                return response.data;
            });
         }

        var service = {
        GetMe: getMe,
        GetUser: getUser,
        AddUser: addUser,
        EditUser: editUser,
        ActivateUser: activateUser
    };

这是我的简化规范调用$ httpBackend.Flush()

describe('Testing httpBackend', function() {

var $httpBackend;

beforeEach(module('mockedCommercial'));


beforeEach(inject(function(_$httpBackend_) {
    $httpBackend = _$httpBackend_;
}))

it('should behave...', function() {

    inject(function(userFactory, $rootScope) {

        var mockData = [];

        $httpBackend.expectGET(wunUtils.constants.serviceBaseUrl + 'FleetUserService.svc/fleetusers/10').respond(mockData);

        var promise = userFactory.GetUser(10);

        $httpBackend.flush();

        promise.then(function(result) {
            expect(result).toEqual(mockData);
        });

        });

});
});

修改

还应该注意,在测试HTTPBackend时,测试只能在使用expectGET和expectPOST时使用,而不是在whenGET和whenPOST时使用。

从我所看到的,whenGet用于模拟数据而expectGet用于测试模拟