2015-06-29 51 views
1

我正在尝试为角度服务编写一个茉莉花测试用例。由于我必须对PouchDB进行调用并获取http资源,因此我使用$ q。茉莉花不会测试具有多个嵌套承诺的角度服务

在我的应用程序中,我有两个数据源:作为localStorage的PouchDB和通过http请求的XML文档。我设法为localStorage.service和XMLparser.service编写测试,没有太多麻烦(我必须做50ms的超时,然后调用$ rootScopre。$ digest())。

但是,当我尝试运行使用localStorage和XMLParser的服务的测试时,我无法让它通过。 Karma挂起5秒钟,测试在超时时失败。如果我在每个地方添加一些console.log(),所有的代码都会被实际执行。就好像done()没有关闭测试用例。如果我直接在我的应用程序中运行代码,它就可以运行

有很多我的代码中去,所以我会尽力解释:

function loadCategories(){ 
    var deferred = $q.defer(); 

    //Json structure that tells my parser what to extract from the XML 
    var structure = { ... } 

    //Check in the PouchDB to see if the structure is already cached 
    localStorage.getStructure() 
    .then(function(struct){ 
     deferred.resolve(struct.category); 
    }) 
    .catch(function(e){ 
     if(e.name != 'not_found') return deferred.reject(e); 

     //If the structure is not cached, get it from the parser through an http request 
     xmlparser.readFile(apiUrl, structure) 
     .then(function(doc){ 
      localStorage.saveStructure(doc); //Save it in the PouchDB 
      deferred.resolve(doc.category); //Resolve with the categories 
     }) 
     .catch(function(e){ 
      deferred.reject(e); 
     }); 
    }); 

    return deferred.promise; 
} 

下面是我测试它:

it('should list the categories', function(done){ 
    //The answer to this call is mocked in the beforeEach 
    $httpBackend.expectGET('/lib/xmlDocuments/indicator.xml'); 

    var promise = Indicator.getCategories() 
    .then(function(categories){ 
     expect(categories[0].name).toBe('Emplois par secteur d\'activité'); 
     expect(categories[1].name).toBe('Emplois par niveau de compétence'); 
     done(); 
     //When i put a console.log here it get executed... 
    }) 
    .catch(function(e){ 
     expect(e).toBe(null); 
    }); 

    //Here i tryed to force a $digest and then flush() the requests 
    //but i still get "Async callback was not invoked within timeout" 
    setTimeout(function() { 
     $scope.$digest(); 
     setTimeout(function(){ 
      $httpBackend.flush(); 
     }, 50); 
    }, 50); 
}); 

现在,我敢肯定,有我做得不好,但我不能把手指放在它上面:

  • 我是否会错过promisses?
  • 我应该模拟XMLParser和localStorage吗?
  • 我的茉莉花是否有错误?
  • 我是否过度使用$ q?

感谢您的帮助!

+0

这不会解决问题,但您不应该在您的服务中使用'$ q'。您应该能够返回'localStorage.getStructure()',因为它返回一个承诺。如果这是一个异步请求,那么你应该嘲笑它。 –

+0

那么,我不能简单地返回localStorage.getStructure(),因为如果结构不在本地数据库中,我需要调用xmlParser.readFile()?我在这里错过了什么吗? – user3220633

+0

如果您从承诺中回复承诺,它会继续链接。你也需要返回'xmlParser.readFile' –

回答

0

好吧,我结束了嘲笑XMLParser和localStorage。我得出结论,再次重新测试这些服务是没有意义的。这是一个单元测试,应该只测试一个单元。

我也修改了我使用承诺的建议,爆炸丸。

//Load the categories 
function loadCategories(){ 
    var structure = { ... } 

    return localStorage.getStructure() 
    .then(function(struct){ 
     return struct.category; 
    }) 
    .catch(function(e){ 
     if(e.name != 'not_found') return e; 

     return xmlparser.readFile(apiUrl, structure) 
     .then(function(doc){ 
      localStorage.saveStructure(doc); 
      return doc.category; 
     }); 
    }); 
} 

我加入了嘲笑为beforeEach

beforeEach(module('gisMobile', function($provide){ 
    xmlParserMock = { 
     readFile: function(){ 
      var defer = $q.defer(); 
      defer.resolve(indicatorJsonMock); 
      return defer.promise; 
     } 
    }; 

    localStorageMock = { 
     isStructureCached: false, 
     getStructure: function(){ 
      var defer = $q.defer(); 
      if(localStorageMock.isStructureCached) 
       defer.resolve(indicatorJsonMock); 
      else 
       defer.reject({name: 'not_found'}); 
      return defer.promise; 
     }, 
     saveStructure: function(){ 
      localStorageMock.isStructureCached = true; 
     } 
    } 

    $provide.value('xmlparser', xmlParserMock); 
    $provide.value('localStorage', localStorageMock); 
})); 

最后的测试现在看起来像

it('should list the categories', function(done){ 
    var promise = Indicator.getCategories() 
    .then(function(categories){ 
     expect(categories[1].name).toBe('Emplois par secteur d\'activité'); 
     expect(categories[0].name).toBe('Emplois par niveau de compétence'); 
     done(); 
    }) 
    .catch(function(e){ 
     expect(e).toBe(null); 
    }); 

    $rootScope.$digest(); 
}); 

所以关闭这个问题,我的假设是正确的:

  • 我没有正确使用
  • 我必须模拟xmlParser和localStorage,因为它们不是此测试的目标。