javascript - Angular 和 Jasmine : how to mock a service that returns a promise

标签 javascript angularjs unit-testing mocking jasmine

我在 AngularJS 中有以下 Controller ,它调用 Angular Material 中的“$mdSidenav”提供的服务。这是由工厂方法提供的服务。

angular.module('leopDirective', [])
    .controller('MenuCtrl', function ($scope,$timeout,$mdSidenav,$log) {

    $scope.mdSidenav = $mdSidenav;
    $scope.close = function () {
        $mdSidenav('left').close().then(function() {$scope.closed=true; });
    };

});

我正在尝试模拟该服务($mdSidenav)以测试我的 Controller 。以下是我尝试定义的 Jasmine 测试的源代码:

describe('Controller: MenuCtrl', function() {
    var $rootScope, $scope, $controller, $q, menuCtrl,
        mock__mdSidenav = function(component) {
            return {
                // THIS FUNCTION IS EMPTY SINCE $Q IS NOT AVAILABLE
                close: function() {}
            }
        };

    beforeEach(function() {
        module('leopDirective', function($provide) {
            // I HAVE TO PROVIDE THE MOCK UP BEFORE INJECTING $Q
            $provide.value('$mdSidenav', mock__mdSidenav);
        });
        inject(function($injector) {
            $rootScope = $injector.get('$rootScope');
            $controller = $injector.get('$controller');
            $q = $injector.get('$q');
            $scope = $rootScope.$new();
        });
        menuCtrl = $controller("MenuCtrl", { $scope: $scope });
    });

    it('should create the $mdSidenav object', function() {
        var deferred = $q.defer(),
            promise = deferred.promise;
        // NOW THAT $Q IS AVAILABLE, I TRY TO FILL UP THE FUNCTION
        mock__mdSidenav.close = function() {
            return promise.then(function(response){return response.success;});
        };
        // force `$digest` to resolve/reject deferreds
        $rootScope.$digest();
        // INVOKE FUNCTION TO TEST
        $scope.close();
    });
});

我遇到的问题是我不知道如何为返回 promise 的模拟创建一个函数:

  1. 创建一个 Promise 取决于 $q,
  2. $q 必须从“inject” block 内注入(inject),
  3. 但是,$provide 必须在“module”内、“inject”之前使用,
  4. 因此,在我的模拟对象中返回 Promise 的函数 (mock__mdSidenav().close()) 在调用“$provide”之前必须为空,并且以某种方式在稍后创建。

使用这种方法,我收到的错误是以下错误(请参阅 演示 plnkr ),它告诉我先创建空函数然后再填充它是行不通的:

TypeError: Cannot read property 'then' of undefined
    at Scope.$scope.close (app.js:7:35)

模拟具有返回 promise 的函数的服务的正确方法是什么?

最佳答案

首先,让mock服务方法返回Promise对象:

mock__mdSidenav = function(component) {
  return {
    isMock: true, 
    close: function() {
        return $q.when();
    }
  }
};

然后将其注入(inject)到 Controller 实例中:

menuCtrl = $controller("MenuCtrl", { 
    $scope: $scope,
    $mdSidenav: mock__mdSidenav
});

最后,写下一些期望:

it('should create the $mdSidenav object', function() {

  $scope.close();
  $rootScope.$digest();

  expect($scope.closed).toBe(true);
});

演示: http://plnkr.co/edit/dr79GgZYG2tjiuWU0oFx?p=preview

关于javascript - Angular 和 Jasmine : how to mock a service that returns a promise,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30005037/

相关文章:

Node.js Mocha 单元测试错误 re : Mongoose mocks with Mockgoose, "Error setting TTL index on collection : sessions"

如果将条件添加到循环中,Javascript 函数将停止工作

javascript - 每 0.5 秒播放一次阵列中的声音

unit-testing - 测试::使用相同的字符串进行更多失败的测试

c# - 注释单元测试c#

javascript - 根据它们的数量在html中对称对齐相同大小的框(divs)

javascript - Three.js 无法渲染 THREE.Points 几何体中的法线

javascript - 从 Background.js 在页面级执行代码并返回值

javascript - 通过 angular.js 中的表单提交将参数传递给路由

javascript - "return"之后的AngularJs括号