Jasmine AngularJS-存储状态/数据的测试工厂

Jasmine AngularJS-存储状态/数据的测试工厂,jasmine,mocha.js,karma-runner,karma-jasmine,Jasmine,Mocha.js,Karma Runner,Karma Jasmine,我正在使用遗留API开发新版本的应用程序(我无法控制API返回的内容等) 在app init上,我请求并存储一些站点范围的工厂信息,我称之为stateFactory。在stateFactory中有类别属性(对象数组),它存储id->category name关系 在我的应用程序模板中,我使用一个过滤器,通过id{{cat_id | categoryNameByIdFilter}提取类别的名称,该过滤器正在stateFactory.categories中进行查找,并返回类别名称 我如何为这些功能(

我正在使用遗留API开发新版本的应用程序(我无法控制API返回的内容等)

在app init上,我请求并存储一些站点范围的工厂信息,我称之为
stateFactory
。在stateFactory中有
类别
属性(对象数组),它存储
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;

    };
}]);

我建议用茉莉花和柠檬。您可以创建一个模拟的
状态工厂
,这样在单元测试时它就不会碰到web服务。我曾经创造过我的模拟和间谍。然后,您可以使用模拟而不是实际服务。这样,唯一被测试的系统是
类别NameByIdFilter
,而不是您的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);
    }));
});

那间谍呢?这有什么用吗?仍然不是关于
spy
背后的概念,你可以在这里使用jasmine spy。不过,我建议使用Sinon。这是一个很棒的javascript模拟框架。你想让我用茉莉花或西农间谍重做溶液吗?好的。我们将不胜感激。一些背景故事,为什么和如何也很好。我添加了西农间谍和模拟。您现在可以对categoryNameByIdFilter spy进行断言,查看其行为是否符合您的预期。非常感谢。我听说过西农,但从来没有机会使用它。我会看透你的例子,希望你能理解发生了什么;)谢谢!