AngularJS, Мокко, Карма. тестирование контроллера, насмешливое сервисное обещание

Я использую AngularJS, Karma, Mocha, Chai, Chai-as-promise, 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» не является функцией (оценка «promise.then.bind (обещание)»

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

sendPhoneNumber(12, 53452123) возвращает Object{$$state: Object{status: 0}}


Я пытался добавить sinon.spy(UserMock, 'sendPhoneNumber'), но это не имеет значения.



person han4wluc    schedule 08.05.2015    source источник


Ответы (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();
}));    
person Phil    schedule 08.05.2015
comment
да, я пытался добавить return User.sendPhoneNumber(..., но это само по себе не решило проблему. Я решил проблему с помощью вашего кода, думаю, благодаря $rootScope или deferred. Этот способ использования deferred действительно хорош. Спасибо. - person han4wluc; 08.05.2015
comment
Может ли кто-нибудь прояснить необходимость вызова rootScope.apply(); ?? - person Gabriel Acosta; 10.10.2015
comment
@gabriel сбрасывает любые невыполненные обещания. Пока вы его не вызовете, обещание останется неразрешенным, и обратный вызов then не будет выполнен. - person Phil; 10.10.2015