在 $rootScope.$apply() 完成解析承诺之前执行的测试规范

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

我正在使用 Jasmine 和 angular-mocks' httpBackend.
编写 angular 单元测试 我已经设法正确地模拟了我的后端,但是我的一些测试在请求完成后(在 then() 中)将值设置为 scope 的 http 调用存在一些问题。

控制器: $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); 执行之前发生。

正如在几个 Whosebug 答案和各种博客文章中所读,我尝试使用 $rootScope.apply(); 但没有成功。

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

你能试试把httpBackend.flush();两行移到上面

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