Pergunta

Parece que promete não resolverem Angular/Jasmim testes, a menos que você force uma $scope.$digest().Isso é bobagem, IMO, mas bem, eu tenho que trabalhar, quando aplicável (controladores).

A situação que eu estou agora é que eu tenho um serviço que poderia cuidar menos sobre qualquer escopos no aplicativo, tudo o que ele faz é retornar alguns dados do servidor, mas a promessa não parece estar a ser resolvido.

app.service('myService', function($q) {
  return {
    getSomething: function() {
      var deferred = $q.defer();
      deferred.resolve('test');
      return deferred.promise;
    }
  }
});

describe('Method: getSomething', function() {
  // In this case the expect()s are never executed
  it('should get something', function(done) {
    var promise = myService.getSomething();

    promise.then(function(resp) {
      expect(resp).toBe('test');      
      expect(1).toEqual(2);
    });

    done();
  });

  // This throws an error because done() is never called.
  // Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
  it('should get something', function(done) {
    var promise = myService.getSomething();

    promise.then(function(resp) {
      expect(resp).toBe('test');      
      expect(1).toEqual(2);
      done();
    });
  });
});

Qual é a maneira correta para testar essa funcionalidade?

Editar:Solução de referência.Aparentemente, você é forçado a injetar e digerir a $rootScope mesmo se o serviço não estiver usando ele.

  it('should get something', function($rootScope, done) {
    var promise = myService.getSomething();

    promise.then(function(resp) {
      expect(resp).toBe('test');      
    });

    $rootScope.$digest();
    done();
  }); 
Foi útil?

Solução

Você precisa injetar $rootScope em seu teste e disparar $digest sobre ele.

Outras dicas

há sempre o $rootScope, usá-lo

inject(function($rootScope){
myRootScope=$rootScope;
})
....

myRootScope.$digest();

Então, eu tenho de estar lutando com isso a tarde toda.Depois de ler este post, eu também senti que havia algo de fora com a resposta;acontece que existe.Nenhuma das respostas acima dá uma clara explicação de como, onde e por que usar $rootScope.$digest.Então, aqui está o que eu encontrei.

Primeiro por que?Você precisa usar $rootScope.$digest sempre que responder a um não-angular de eventos ou de retorno de chamada.Isso inclui puro DOM de eventos, jQuery, eventos, e outras 3rd party Promessa de bibliotecas que $q qual é a parte angular.

Em segundo lugar, onde?No seu código, e NÃO o seu teste.Não é necessário injetar $rootScope em seu teste, é necessária apenas em sua real angular de serviço.Que é onde tudo acima falhar, deixar claro que a resposta é, eles mostram $rootScope.$digest como está sendo chamado de teste.

Espero que isso ajude a próxima pessoa que vem de uma longa, que tem o mesmo problema.

Atualização


Eu apaguei esse post de ontem, quando ele tem votado para baixo.Hoje eu continuava a ter esse problema ao tentar usar as respostas, graciosamente fornecido acima.Então, eu espera a minha resposta o custo de pontos de reputação e, como tal , estou desfazendo-lo.

Isso é o que você precisa em manipuladores de eventos que não são angulares, e você estiver usando o $q e tentar testar com Jasmine.

something.on('ready', function(err) {
    $rootScope.$apply(function(){deferred.resolve()});              
});

Observe que ele pode precisar de ser envolvido em um jogo de $tempo de espera em alguns casos.

something.on('ready', function(err) {
    $timeout(function(){
      $rootScope.$apply(function(){deferred.resolve()});    
    });     
});

Uma observação mais.No problema original exemplos que você está chamando done na hora errada.Você precisa chamar done dentro do then o método (ou o catch ou finally), da promessa, depois é resolvida.Você está chamando-o antes que a promessa resolve, o que está causando o it cláusula terminar.

A partir angular documentação.

https://docs.angularjs.org/api/ng/service/$q

it('should simulate promise', inject(function($q, $rootScope) {
  var deferred = $q.defer();
  var promise = deferred.promise;
  var resolvedValue;

  promise.then(function(value) { resolvedValue = value; });
  expect(resolvedValue).toBeUndefined();

  // Simulate resolving of promise
  deferred.resolve(123);
  // Note that the 'then' function does not get called synchronously.
  // This is because we want the promise API to always be async, whether or not
  // it got called synchronously or asynchronously.
  expect(resolvedValue).toBeUndefined();

  // Propagate promise resolution to 'then' functions using $apply().
  $rootScope.$apply();
  expect(resolvedValue).toEqual(123);
}));
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top