如何测试我AngularJS控制器时,我嘲笑的结果在$ http.get承诺? [英] How do I mock the result in a $http.get promise when testing my AngularJS controller?

查看:171
本文介绍了如何测试我AngularJS控制器时,我嘲笑的结果在$ http.get承诺?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大量的阅读之后,似乎推荐的方法来调用从AngularJS控制器Web服务是使用一个工厂,并返回从一个承诺。

在这里,我有一个简单的工厂,调用示例API。

  myApp.factory('MyFactory',['$ HTTP',函数($ HTTP){
变种人= {
        requestPeople:函数(X){
            VAR URL ='JS / test.json';
            返回$ http.get(URL);
        }
    };
返回的人;
}]);

这就是我称之为控制器

  myApp.controller('MyCtrl1',['$范围,MyFactory',函数($范围,MyFactory){
        MyFactory.requestPeople(22)。然后(功能(结果){
             $ scope.peopleList =结果;
        });
}]);

虽然它工作得很好,我希望能够嘲笑结果传递进来的时候然后被调用。这可能吗?

我尝试迄今已生产什么。这是我尝试:

  //假服务
VAR mockService = {
    requestPeople:功能(){
        返回{
            则:函数(){
                返回{一:三};
            }
        }    }
};
//一些设置
beforeEach(模块('myApp.controllers'));
VAR CTRL,范围;beforeEach(注(函数($ rootScope,$控制器){
    范围= $ rootScope $新的()。    CTRL = $控制器('MyCtrl1',{$适用范围:适用范围,MyFactory:mockService});
}));//测试
它('事件类型空应该默认为假,注入(函数(){
    期待(scope.peopleList.one).toBe('三');
}));

在因果报应亚军运行此当我得到的错误,是

类型错误:未定义是不是(评估'scope.peopleList.one')

对象

我怎样才能得到我的嘲讽数据本次测试工作吗?


解决方案

我不认为$ httpBackend是什么你在这里后,你想,而不必在$依赖HTTP它被嘲笑全厂<? / p>

看看 $ Q ,特别是测试标题下的code样品。您的问题可能与code,看起来像这样来解决:

 使用严格的;描述(嘲讽工厂响应',函数(){    beforeEach(模块('myApp.controllers'));    VAR范围,fakeFactory,控制器,Q,推迟;    // prepare假厂
    beforeEach(函数(){
        fakeFactory = {
            requestPeople:功能(){
                递延= q.defer();
                //此处将假返回对象
                deferred.resolve({一:三化});
                返回deferred.promise;
            }
        };
        spyOn(fakeFactory,'requestPeople')andCallThrough()。
    });    //注入假厂发展成为控制器
    beforeEach(注(函数($ rootScope,$控制器,$ Q){
        范围= $ rootScope $新的()。
        Q = $ Q;
        控制器= $控制器('MyCtrl1',{$适用范围:适用范围,MyFactory:fakeFactory});
    }));    它('的peopleList对象没有定义尚未',函数(){
        // $之前调用Apply的承诺一直没有得到解决
        期待(scope.peopleList).not.toBeDefined();
    });    它('应用范围使得它被定义',函数(){
        //此更改传播到模型
        //这种情况本身,当你在网页上,而不是在一个单元测试框架
        。范围$适用();
        期待(scope.peopleList).toBeDefined();
    });    它('确保调用方法',函数(){
        。范围$适用();
        期待(fakeFactory.requestPeople).toHaveBeenCalled();
    });    它('检查返回值',函数(){
        。范围$适用();
        期待(scope.peopleList).toBe({一:三化});
    });
});

我添加了周围什么$申请呢,我不知道一些测试,直到我开始玩这个!

高格

After much reading, it seems that the recommended way to call a web service from an AngularJS controller is to use a factory and return a promise from that.

Here I have a simple factory which calls a sample API.

myApp.factory('MyFactory', ['$http',function($http) {
var people = {
        requestPeople: function(x) {
            var url = 'js/test.json';
            return $http.get(url);
        }
    };
return people;
}]);

And this is how I call it in the controller

myApp.controller('MyCtrl1', ['$scope', 'MyFactory', function ($scope, MyFactory) {
        MyFactory.requestPeople(22).then(function(result) {
             $scope.peopleList = result;
        });
}]);

While it works fine, I would like to be able to mock the result that is passed in when then is called. Is this possible?

My attempt so far has produced nothing. This is my attempt:

//Fake service
var mockService = {
    requestPeople: function () {
        return {
            then: function () {
                return {"one":"three"};
            }
        }

    }
};


//Some setup
beforeEach(module('myApp.controllers'));
var ctrl, scope;

beforeEach(inject(function ($rootScope, $controller) {
    scope = $rootScope.$new();

    ctrl = $controller('MyCtrl1', { $scope: scope, MyFactory: mockService });
}));

//Test
it('Event Types Empty should default to false', inject(function () {
    expect(scope.peopleList.one).toBe('three');
}));

The error that I get when running this in karma runner, is

TypeError: 'undefined' is not an object (evaluating 'scope.peopleList.one')

How can I get this test working with my mocked data?

解决方案

I don't think $httpBackend is what you're after here, you want the whole factory to be mocked without it having a dependency on $http?

Take a look at $q, in particular the code sample under the Testing header. Your issue might be resolved with code that looks like this:

'use strict';

describe('mocking the factory response', function () {

    beforeEach(module('myApp.controllers'));

    var scope, fakeFactory, controller, q, deferred;

    //Prepare the fake factory
    beforeEach(function () {
        fakeFactory = {
            requestPeople: function () {
                deferred = q.defer();
                // Place the fake return object here
                deferred.resolve({ "one": "three" });
                return deferred.promise;
            }
        };
        spyOn(fakeFactory, 'requestPeople').andCallThrough();
    });

    //Inject fake factory into controller
    beforeEach(inject(function ($rootScope, $controller, $q) {
        scope = $rootScope.$new();
        q = $q;
        controller = $controller('MyCtrl1', { $scope: scope, MyFactory: fakeFactory });
    }));

    it('The peopleList object is not defined yet', function () {
        // Before $apply is called the promise hasn't resolved
        expect(scope.peopleList).not.toBeDefined();
    });

    it('Applying the scope causes it to be defined', function () {
        // This propagates the changes to the models
        // This happens itself when you're on a web page, but not in a unit test framework
        scope.$apply();
        expect(scope.peopleList).toBeDefined();
    });

    it('Ensure that the method was invoked', function () {
        scope.$apply();
        expect(fakeFactory.requestPeople).toHaveBeenCalled();
    });

    it('Check the value returned', function () {
        scope.$apply();
        expect(scope.peopleList).toBe({ "one": "three" });
    });
});

I've added some tests around what $apply does, I didn't know that until I started playing with this!

Gog

这篇关于如何测试我AngularJS控制器时,我嘲笑的结果在$ http.get承诺?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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