测试规范在$rootScope之前执行$apply()已完成对promise的解析

Test spec executing before $rootScope.$apply() is done resolving promise

本文关键字:已完成 promise 执行 rootScope 测试 apply      更新时间:2023-09-26

我正在使用带有angular-mocks'httpBackend的Jasmine编写角度单元测试
我已经成功地模拟了我的后端,但我的某个测试在http调用中遇到了一些问题,在请求完成后,值被设置为scope(在then()中)。

控制器:$scope.startShift绑定到按钮点击。

 app.controller('ShiftStartCntl', function($scope, $rootScope, $location, Restangular, $http, shifts) {
    $scope.shifts = shifts;
    $scope.startShift = function (category) {
        $scope.startingShift = true;
        baseShifts.post({category_number: 2})
            .then(function (shift) {
                $scope.shift = shift;
                // breaks here if run as the endpoint isn't mocked
                $http.post('endpointThatIsNotMocked').then(function() {});
                $location.path($scope.rootURL + '/shift/' + shift.id + '/');
                $scope.startingShift = false;
        });
});

测试:

// module definition and stuff
// 
// [...]
// 
describe('ShiftStartCntl', function() {
    var scope, rootScope, httpBackend, ShiftStartCntl;
    beforeEach(angular.mock.inject(function($rootScope, $controller, $httpBackend) {
        scope = $rootScope.$new();
        rootScope = $rootScope;
        httpBackend = $httpBackend;
        // mimics the controller's ng-route `resolve` dependency
        shifts = getJSONFixture('leave_shifts.json');
        scope.baseShifts = baseApi.all('shifts');
        // used in the controller
        scope.categories = getJSONFixture('leave_categories.json');
        httpBackend.expectPOST('/api/shifts/', {category_number: 2})
            .respond(203, {"id": 4,                                                                                                                                                                  "user": 1,
                "category_number": 2,
                "sign_in": "2015-02-10T21:29:06.110Z",
                "sign_out": null
            });
        $controller('ShiftStartCntl', {$scope: scope, shifts: []});
    }));
    it('should start a shift', function() {
        expect(shifts.length).toEqual(2);
        expect(scope.startingShift).toBe(undefined);
        scope.startShift(scope.categories[1]);
        rootScope.$apply();
        expect(scope.shift.id).toEqual(4);
        httpBackend.flush();
    });
});

产生的错误如下:

PhantomJS 1.9.8 (Mac OS X) Shifts ShiftStartCntl should start a shift FAILED
        Expected undefined to equal 4.
            at [...]/js/tests/unit/controllers/main.js:100  
        Error: Unexpected request: POST yoyoyo

expect(scope.shift.id).toEqual(4); 所在的线路

我的问题是,关于意外请求的错误应该在执行expect(scope.shift.id).toEqual(4);之前发生。

正如在一些Stackoverflow的回答和各种博客文章中所读到的,我尝试过使用$rootScope.apply();,但没有成功。

关于如何解决这个问题,有什么想法吗?

你能试着把httpBackend.flush();移到上方两行吗

        scope.startShift(scope.categories[1]);
        httpBackend.flush();
        rootScope.$apply();
        expect(scope.shift.id).toEqual(4);