嘲讽服务和承诺 - 在AngularJS单元测试 [英] Unit testing in AngularJS - Mocking Services and Promises

查看:126
本文介绍了嘲讽服务和承诺 - 在AngularJS单元测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在角一切似乎有一个陡峭的学习曲线和单元测试的角度应用绝对不逃避这个范例。

In Angular everything seems to have a steep learning curve and unit testing an Angular app definitely doesn't escape this paradigm.

当我开始与TDD和角度我觉得我几乎花光了两次(也许更多)尽可能多的时间搞清楚如何去测试,甚至更多的只是让我的测试中正确设置。但作为<一href=\"http://www.bennadel.com/blog/2439-My-Experience-With-AngularJS-The-Super-heroic-JavaScript-MVW-Framework.htm\">Ben纳德尔把它放在自己的博客上有大起大落的角度学习过程。他的图肯定是我的角度体验。

When I started with TDD and Angular I felt that I was spending twice (maybe more) as much time figuring out just how to test and maybe even more just getting my tests set up correctly. But as Ben Nadel put it in his blog there are ups and downs in the angular learning process. His graph is definitely my experience with Angular.

不过,我在学习角和单元测试以及取得了进展,现在我觉得我花少得多的时间建立测试和更多的时间去测试去由红变绿 - 这是一个很好的感觉。

However as I have progressed in learning Angular and unit testing as well, now i feel that I am spending much less time setting up tests and much more time making tests go from red to green - which is a good feeling.

所以,我所遇到我的单元测试设置为模拟服务和承诺的不同的方法,我想我会分享我所学,也问了一个问题:

So I have come across different methods of setting up my unit test to mock services and promises and I thought I would share what I have learned and also ask the question of:

有没有实现这一点的任何其他或更好的办法呢?

Are there any other or better ways of accomplishing this?

所以到code,什么大家都来这里反正 - 不要听一些人讲他的爱情,宁可成就学习的框架。

So onto the code, that what we all come for here anyways - not to listen to some guy talk about his love, err accomplishments learning a framework.

这是我开始了我的嘲讽服务和承诺,我将使用一个控制器,但服务和承诺可以在其他地方显然被嘲笑。

This is how I started out mocking my services and promises, I'll use a controller, but services and promises can be mocked in other places obviously.

describe('Controller: Products', function () {
    var//iable declarations
        $scope,
        $rootScope,
        ProductsMock = {
            getProducts: function () {
            } // There might be other methods as well but I'll stick to one for the sake of consiseness
        },
        PRODUCTS = [{},{},{}]
    ;

    beforeEach(function () {
        module('App.Controllers.Products');
    });

    beforeEach(inject(function ($controller, _$rootScope_) {
        //Set up our mocked promise
        var promise = { then: jasmine.createSpy() };

        //Set up our scope
        $rootScope = _$rootScope_;
        $scope = $rootScope.$new();

        //Set up our spies
        spyOn(ProductsMock, 'getProducts').andReturn(promise);

        //Initialize the controller
        $controller('ProductsController', {
            $scope: $scope,
            Products: ProductsMock
        });

        //Resolve the promise
        promise.then.mostRecentCall.args[0](PRODUCTS);

    }));

    describe('Some Functionality', function () {
        it('should do some stuff', function () {
            expect('Stuff to happen');
        });
    });
});

有关我们这个工作,但随着时间的推移,我认为必须有一个更好的办法。对于一个我讨厌

For us this worked, but as time went on I thought there must be a better way. For one I hated the

promise.then.mostRecentCall 

的事情的,如果我们想重新初始化控制器,然后我们不得不将其拉出beforeEach块并分别注射到每个测试。

thing, and if we wanted to reinitialise the controller then we had to pull it out of the beforeEach block and inject it individually into each test.

必须有一个更好的办法...

There has to be a better way...

现在我问有没有人有其他的方式来设置的测试,或者和想法或我必须选择做它的方式感觉怎么样?

Now I ask does anyone have other ways to set tests up, or and thoughts or feeling on the way I have chose to do it?

推荐答案

然后,我遇到了另一篇文章,博客,例如计算器(你拿起它,我可能是在那里),我看到使用$ Q库。咄!为什么要建立一个全模拟的承诺的时候,我们可以只使用该角度为我们提供了工具。我们code看起来更好和更有意义来看 - 没有丑女promise.then.mostRecent的的事情的。

Then I came across another post, blog, stackoverflow example (you pick it I was probably there), and I saw the use of the $q library. Duh! Why set up a whole mock promise when we can just use the tool that Angular gives us. Our code looks nicer and makes more sense to look at - no ugly promise.then.mostRecent thing.

在单元测试的迭代下是这样的:

Next in the iteration of unit testing was this:

describe('Controller: Products', function () {
    var//iable declarations
        $scope,
        $rootScope,
        $q,
        $controller,
        productService,
        PROMISE = {
            resolve: true,
            reject: false
        },
        PRODUCTS = [{},{},{}] //constant for the products that are returned by the service
    ;

    beforeEach(function () {
        module('App.Controllers.Products');
        module('App.Services.Products');
    });


    beforeEach(inject(function (_$controller_, _$rootScope_, _$q_, _products_) {
        $rootScope = _$rootScope_;
        $q = _$q_;
        $controller = _$controller_;
        productService = _products_;
        $scope = $rootScope.$new();
    }));

    function setupController(product, resolve) {
        //Need a function so we can setup different instances of the controller
        var getProducts = $q.defer();

        //Set up our spies
        spyOn(products, 'getProducts').andReturn(getProducts.promise);

        //Initialise the controller
        $controller('ProductsController', {
            $scope: $scope,
            products: productService
        });

        // Use $scope.$apply() to get the promise to resolve on nextTick().
        // Angular only resolves promises following a digest cycle,
        // so we manually fire one off to get the promise to resolve.
        if(resolve) {
            $scope.$apply(function() {
                getProducts.resolve();
            });
        } else {
            $scope.$apply(function() {
                getProducts.reject();
            });
        }
    }

    describe('Resolving and Rejecting the Promise', function () {
        it('should return the first PRODUCT when the promise is resolved', function () {
            setupController(PRODUCTS[0], PROMISE.resolve); // Set up our controller to return the first product and resolve the promise. 
            expect('to return the first PRODUCT when the promise is resolved');
        });

        it('should return nothing when the promise is rejected', function () {
            setupController(PRODUCTS[0], PROMISE.reject); // Set up our controller to return first product, but not to resolve the promise. 
            expect('to return nothing when the promise is rejected');
        });
    });
});

这开始觉得它应该被设置方式。我们可以嘲笑我们需要模拟,我们可以设置我们的承诺,以解决和拒绝,所以我们才能真正测试两种可能的结果。这感觉很好...

This started to feel like the way it should be set up. We can mock what we need to mock we can set our promise to resolve and reject so we can truly test the two possible outcomes. This feels good...

这篇关于嘲讽服务和承诺 - 在AngularJS单元测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆