2014-09-11 23 views
1

我正在使用传统API(我无法控制什么API返回等)的新版本的应用程序。AngularJS - 存储状态/数据的测试工厂

在应用程序初始化我请求&存储一些网站的信息我叫stateFactory的工厂。在stateFactory里面有categories属性(对象的数组),它存储着关系id -> category name

在我的应用程序模板内我使用过滤器来提取类别的名称,ID为{{ cat_id | categoryNameByIdFilter }},它在stateFactory.categories中执行查找并返回类别名称。

如何为这样的功能编写单元测试(茉莉花,摩卡,柴,什么)?

// represantion of what the stateFactory looks like with some data in it 
app.factory('stateFactory', ['', function(){ 
    return { 
     categories = [ 
      { cat_id: 1, cat_name: "some category name" }, 
      { cat_id: 2, cat_name: "another category name" } 
     ]; 
    }; 
}]) 

// categoryNameByIdFilter 
app.factory('categoryNameByIdFilter', ['stateFactory', function(stateFactiry){ 
    return function(cat_id){ 

     if (!cat_id) return null; 
     var cat_obj = _.findWhere(stateFactiry.categories, { 
      id: cat_id 
     }); 
     if (!cat_obj) return null; 
     return cat_obj.cat_name; 

    }; 
}]); 

回答

1

我建议使用茉莉花和angular's mock module。您可以创建一个stateFactory的模拟,以便它在单元测试时不会触及Web服务。我用Sinon来创建我的嘲笑和间谍。那么,你可以用角度注入你的模拟而不是真正的服务。这样,唯一被测试的系统是categoryNameByIdFilter而不是您的Web服务。

// representation of what the stateFactory looks like with some data in it 
app.factory('stateFactory', ['', function() 
{ 
    return function() 
    { 
     //This is the real stateFactory, which we are going to mock out. 
    }; 
}]); 

// categoryNameByIdFilter - The system under test in this example 
app.factory('categoryNameByIdFilter', ['stateFactory', '_', function (stateFactiry, _) 
{ 
    return function (cat_id) 
    { 

     if (!cat_id) return null; 
     var cat_obj = _.findWhere(stateFactiry.categories, { 
      id: cat_id 
     }); 
     if (!cat_obj) return null; 
     return cat_obj.cat_name; 

    }; 
}]); 

鉴于上面的代码,我们可以做这个测试categoryNameByIdFilter ...

describe("categoryNameByIdFilter", function() 
{ 
    beforeEach(module('YOUR_APP_MODULE')); 
    beforeEach(function() 
    { 
     //The following line creates a mock of what we expect the state factory to return. 
     //We're mocking this because it is no the system under test, the filter is. 

     //A sinon 'stub' is a spy 
     mockStateFactory = sinon.stub({ 
      categories: [ 
       { id: 1, cat_name: "some category name" }, 
       { id: 2, cat_name: "another category name" } 
      ] 
     }); 
     module(function ($provide) 
     { 
      //When Angular asks for a stateFactory, give them this mock instead 
      $provide.value('stateFactory', mockStateFactory); 
     }); 
    }); 

    //You can inject a filter using the "inject" method below 
    it("should filter by id", inject(function (categoryNameByIdFilter) 
    { 
     //Wrap categoryNameByIdFilter in a spy so that we can make assertions off of it. 
     var spy = sinon.spy(categoryNameByIdFilter); 
     var result = spy(1); 
     expect(result).toEqual("some category name"); 
     expect(spy.calledBefore(mockStateFactory)).toBeTruthy(); 
     expect(spy.returned("some category name")).toBeTruthy(); 
     sinon.assert.calledOnce(spy); 
     spy(2);//Returns something besides "some category name" 
     expect(spy.alwaysReturned("some category name")).not.toBeTruthy(); 
     sinon.assert.calledTwice(spy); 
    })); 
}); 
+0

怎么样'spy'?这可以在这里使用吗?仍然不是关于'间谍'背后的概念 – Iladarsda 2014-09-11 13:30:00

+1

你可以在这里使用茉莉间谍。不过,我会建议使用Sinon。这是一个梦幻般的JavaScript嘲笑框架。您是否希望我使用茉莉或Sinon间谍来重做解决方案? – Onosa 2014-09-11 13:32:37

+0

是的。这将非常感激。一些背景故事,为什么以及如何将会很好。 – Iladarsda 2014-09-11 13:33:45