测试asynchrone函数会产生意外请求

时间:2013-09-20 14:35:54

标签: unit-testing angularjs asynchronous jasmine

单元测试:

"use strict";

var usersJSON = {};

describe("mainT", function () {


 var ctrl, scope, httpBackend, locationMock, 

    beforeEach(module("testK"));
    beforeEach(inject(function ($controller, $rootScope, $httpBackend, $location, $injector) {
        scope = $rootScope.$new();
        httpBackend = $httpBackend;
        locationMock = $location;

        var lUrl = "../solr/users/select?indent=true&wt=json",
        lRequestHandler = httpBackend.expect("GET", lUrl);          
        lRequestHandler.respond(200, usersJSON);     

        ctrl = $controller("mainT.controller.users", { $scope: scope, $location: locationMock});
        httpBackend.flush();
        expect(scope.users).toBeDefined();

    }));

    afterEach(function () {
        httpBackend.verifyNoOutstandingRequest();
        httpBackend.verifyNoOutstandingExpectation();
    });




        describe("method test", function () {
        it('should test', function () {
            expect(true).toBeFalsy();
        });
    });
});

控制器我正在测试(工作): init中的Asynchrone函数给我带来了麻烦(使用../ solr / users / select?indent = true& wt = json):

 $scope.search = function () {
                    var lStart = 0,
                        lLimit = privates.page * privates.limit;


                    Search.get({
                        collection: "users",
                        start: lStart,
                        rows: lLimit)
                    }, function(records){
                        $scope.users= records.response.docs;
                    });
                };

我认为发生了什么:
1.告知后端他将收到什么请求 2.通过后端通知空JSON的请求响应 3.创建一个控制器(Search.get get执行)
4.通知后端接收所有请求并回答(冲洗)

然而,我总是得到以下错误:

Error: Unexpected request: GET : ../solr/users/select?indent=true&wt=json

我没有很好地处理异步检索功能吗?应该怎么做?

3 个答案:

答案 0 :(得分:3)

这不是真正的“单元”测试,而是更多的行为测试。

这应该是一些测试:

  1. 测试您的服务Search.get以确保它的调用正确的网址并返回结果。
  2. 测试您的控制器方法以确保它正在调用Search.get
  3. 测试您的控制器方法,以确保它将结果放在适当的位置。
  4. 您发布的代码有点不完整,但这里有两个单元测试应该覆盖您:

    这是我在博客上广泛讨论的内容,条目更详细:

    这是我正在谈论的一个例子:

    describe('Search', function () {
        var Search,
            $httpBackend;
    
        beforeEach(function () {
            module('myModule');
    
            inject(function (_Search_, _$httpBackend_) {
                Search = _Search_;
                $httpBackend = _$httpBackend_;
            });
        });
    
        describe('get()', function () {
            var mockResult;
    
            it('should call the proper url and return a promise with the data.', function () {
                mockResult = { foo: 'bar' };
                $httpBackend.expectGET('http://sample.com/url/here').respond(mockResult);
    
                var resultOut,
                    handler = jasmine.createSpy('result handler');
                Search.get({ arg1: 'wee' }).then(handler);
    
                $httpBackend.flush();
    
                expect(handler).toHaveBeenCalledWith(mockResult);
    
                $httpBackend.verifyNoOutstandingRequest();
                $httpBackend.verifyNoOutstandingExpectation();
    
    
            });
        });
    
    });
    
    describe('myCtrl', function () {
        var myCtrl,
            $scope,
            Search;
    
        beforeEach(function () {
            module('myModule');
    
            inject(function ($rootScope, $controller, _Search_) {
                $scope = $rootScope.$new();
                Search = _Search;
                myCtrl = $controller('MyCtrl', {
                    $scope: scope
                });
            });
        });
    
        describe('$scope.foo()', function () {
            var mockResult = { foo: 'bar' };
    
            beforeEach(function () {
                //set up a spy.
                spyOn(Search, 'get').andReturn({
                    then: function (fn) {
                        // this is going to execute your handler and do whatever
                        // you've programmed it to do.. like $scope.results = data; or
                        // something.
                        fn(mockResult);
                    }
                });
    
                $scope.foo();
            });
    
            it('should call Search.get().', function () {
                expect(Search.get).toHaveBeenCalled();
            });
    
            it('should set $scope.results with the results returned from Search.get', function () {
                expect(Search.results).toBe(mockResult);
            });
        });
    
    });
    

答案 1 :(得分:2)

单元测试中的lUrl不应该是相对路径,即代替“../solr/users/select?indent=true&wt=json”它应该是绝对的“ ?/ solr的/用户/选择缩进=真安培;重量= JSON”。因此,如果您的应用程序在"http://localhost/a/b/index.html"运行,则lUrl应为"/a/solr/..."

请注意,您也可以在$httpBackend.expectGET()中使用正则表达式,如果您不完全确定以后绝对路径的样子,这可能会有所帮助。

答案 2 :(得分:2)

在BeforeEach中,你应该使用httpBackend.when而不是httpBackend.expect。我不认为你的BeforeEach中应该有一个断言(expect),所以应该将它移到一个单独的it()块中。我也没有看到lRequestHandler的定义。默认情况下会发送200状态,因此不需要。您的httpBackend行应如下所示:

httpBackend.when("GET", "/solr/users/select?indent=true&wt=json").respond({});

您的测试应该是:

    describe("method test", function () {
        it('scope.user should be defined: ', function () {
            expect(scope.user).toEqual({});
        });
    });