【问题标题】:AngularJS - testing factories which store state/dataAngularJS - 测试存储状态/数据的工厂
【发布时间】:2014-09-11 10:47:41
【问题描述】:

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

在应用程序初始化中,我请求并存储一些站点范围的信息,我称之为 stateFactory。 stateFactory 内部有categories 属性(对象数组),它存储id -> category name 关系。

在我的应用模板中,我使用过滤器通过 id {{ cat_id | categoryNameByIdFilter }} 提取类别名称,它在 stateFactory.categories 中进行查找并返回类别名称。

如何为此类功能(jasmine、mocha、chai 等)编写单元测试?

// 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;

    };
}]);

【问题讨论】:

    标签: jasmine mocha.js karma-runner karma-jasmine


    【解决方案1】:

    我建议使用 Jasmine 和 angular's mock module。您可以创建 stateFactory 的模拟,以便在单元测试时它不会访问 Web 服务。我使用Sinon 来创建我的模拟和间谍。然后,您可以有角度地注入您的模拟而不是真正的服务。这样,唯一被测试的系统是categoryNameByIdFilter 而不是您的网络服务。

    // 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 怎么样?这在这里有用吗?仍然不是关于spy背后的概念@
    • 你可以在这里使用茉莉间谍。不过,我建议使用Sinon。这是一个很棒的 javascript 模拟框架。你想让我用茉莉花或诗浓间谍重做解决方案吗?
    • 请。那将不胜感激。一些背景故事,为什么以及如何也会很棒。
    • 我添加了诗乃间谍和嘲讽。您现在可以对 categoryNameByIdFilter 间谍进行断言,以查看它的行为是否符合您的预期。
    • 非常感谢。我听说过诗乃,但一直没有机会使用它。我会通过你的例子,希望你能理解发生了什么;)谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-20
    • 2017-10-07
    • 1970-01-01
    • 2014-02-20
    相关资源
    最近更新 更多