AngularJs单元测试 - 嘲笑承诺不执行"然后"单元测试、AngularJs、QUOT

2023-09-13 04:33:50 作者:心有困兽

我们正在单元测试我们的控制器。我们已经成功地嘲笑调用了REST服务层并验证它确实被称为给定的数据。但是现在我们想测试我们的控制器执行然后承诺改变了 location.path

We're unit testing our controllers. We've successfully mocked the call to our REST service layer and verified that it is indeed being called with the given data. Now however we'd like to test that in our controller the execution of the then promise changes the location.path:

控制器:

(function () {

    app.controller('registerController', ['$scope', '$location', '$ourRestWrapper', function ($scope, $location, $ourRestWrapper) {

    $scope.submitReg = function(){
        // test will execute this
        var promise = $ourRestWrapper.post('user/registration', $scope.register);

        promise.then(function(response) {    
                console.log("success!"); // test never hits here           
                $location.path("/");
        },
            function(error) {
                console.log("error!"); // test never hits here
                $location.path("/error");
            }
        );
    };

$ ourRestWrapper.post(网址,数据)只是包装 Restangular.all(URL)。员额(数据) ..

我们的测试:

(function () {

    describe("controller: registerController", function() {

        var scope, location, restMock, controller, q, deferred;

        beforeEach(module("ourModule"));

        beforeEach(function() {
            restMock = {
                post: function(url, model) {
                    console.log("deferring...");
                    deferred = q.defer();    
                    return deferred.promise;
                }
            };
        });

        // init controller for test
        beforeEach(inject(function($controller, $rootScope, $ourRestWrapper, $location, $q){
            scope = $rootScope.$new();
            location = $location;
            q = $q;

            controller = $controller('registerController', {
                $scope: scope, $location: location, $ourRestWrapper: restMock});
        }));

    it('should call REST layer with registration request', function() {
        scope.register = {data:'test'};

        spyOn(restMock, 'post').andCallThrough();

        scope.submitReg();

        deferred.resolve();

        // successfull
        expect(restMock.post).toHaveBeenCalledWith('user/registration',scope.register);
        expect(restMock.post.calls.length).toEqual(1);
        // fail: Expected '' to be '/'.
        expect(location.path()).toBe('/');
    });

在我们的控制台,我们看到推迟......与前两部的预期成功。它为什么不叫然后块(即设置的位置)?

In our console we see "deferring..." and the first two expectations succeed. Why will it not call the then block (i.e. set the location)?

推荐答案

缓存当你从注射器得到它并调用 $ rootscope 对象 $ rootScope。$适用()后,立即 deferred.resolve()

Cache the $rootscope object when you get it from the injector and call $rootScope.$apply() immediately after deferred.resolve().