【问题标题】:AngularJS, Mocha, Karma. testing controller, mocking service promiseAngularJS,摩卡,业力。测试控制器,模拟服务承诺
【发布时间】:2015-05-08 01:16:06
【问题描述】:

我正在使用 AngularJS、Karma、Mocha、Chai、Chai-as-promised、Sinon。
我正在尝试下面的控制器。我无法模拟服务用户并测试控制器中的 .then() 部分。

控制器代码

.controller('SignupPhoneCtrl', function(User, $scope) {
  $scope.sendPhoneNumber = function(countryCode, phoneNumber){
    User.sendPhoneNumber(countryCode, phoneNumber)
    .then(function(result){
      if(result == "success"){
        //I WANT TO TEST THIS SECTION
        return "success";
      }
        //I WANT TO TEST THIS SECTION
      return "fail";
    });
  }
})

控制器测试代码

describe('Controller: Signup-phone', function() {
  var scope;
  var UserMock;
  var SignupPhoneCtrl;

  beforeEach(function() {
    module('starter.controllers');
  });

  beforeEach(inject(function($rootScope, $controller, $q){
    scope = $rootScope.$new();
    UserMock = {
      sendPhoneNumber: function(countryCode, phoneNumber){
        var deferred = $q.defer();
        // console.log("called"); //This part is being called
        deferred.resolve('foo');
        return deferred.promise;
      }
    };
    SignupPhoneCtrl = $controller("SignupPhoneCtrl", {$scope: scope, User: UserMock});
  }))

  it('should return asdf', function(){
    scope.$digest();

    //WHAT SHOULD I WRITE HERE?

  })
});


我已经尝试了以下方法,但没有调用断言部分。

scope.sendPhoneNumber(12, 53452123).then(function(result){
  result.should.equal("fail");  //THIS SECTION IS NOT CALLED
})

我尝试了以下方法,但它给出了错误:'undefined' is not a function (evalating 'promise.then.bind(promise)'

scope.sendPhoneNumber(12, 53452123).should.eventually.equal("fail");

sendPhoneNumber(12, 53452123) 返回Object{$$state: Object{status: 0}}


我尝试添加sinon.spy(UserMock, 'sendPhoneNumber'),但没有任何区别。


【问题讨论】:

    标签: angularjs promise mocha.js karma-runner chai


    【解决方案1】:

    问题是,$scope.sendPhoneNumber 没有返回任何内容。试试

    return User.sendPhoneNumber(...
    

    在你的控制器方法中。


    另外,如果你只是想立即解决你的模拟中的承诺,我发现这很有效,并且可以节省你设置延迟对象的时间

    UserMock = {
      sendPhoneNumber: function(countryCode, phoneNumber){
        return $q.when('foo');
      }
    };
    

    话虽如此,您可能希望能够控制每个测试中的解析值,这样更有意义...

    var scope;
    var UserMock;
    var SignupPhoneCtrl;
    var deferred;
    
    // snip
    
    inject(function($rootScope, $controller, $q) {
        deferred = $q.defer();
        UserMock = {
            sendPhoneNumber: function() {
                return deferred.promise;
            }
        };
    });
    
    // snip
    
    it('tests for success', inject(function($rootScope) {
        deferred.resolve('success');
    
        scope.sendPhoneNumber(...).then(...);
    
        $rootScope.$apply();
    }));
    
    it('tests for failure', inject(function($rootScope) {
        deferred.resolve('not success');
    
        scope.sendPhoneNumber(...).then(...);
    
        $rootScope.$apply();
    }));    
    

    【讨论】:

    • 是的,我曾尝试添加return User.sendPhoneNumber(...,但仅此一项并不能解决问题。我使用您的代码解决了这个问题,我认为这要归功于 $rootScope 或 deferred。这种使用 deferred 的方式非常好,谢谢。
    • 谁能说明需要调用 rootScope.apply(); ??
    • @gabriel 它会刷新所有未解决的承诺。在你调用它之前,promise 将保持未解决,then 回调将不会运行
    猜你喜欢
    • 2015-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-14
    • 1970-01-01
    • 1970-01-01
    • 2022-11-27
    • 2017-06-03
    相关资源
    最近更新 更多