为什么我的 Angular 应用程序的 jasmine 测试失败

Why is my jasmine test failing for my Angular app

我有以下代码...其中一个测试失败了。请帮助我理解原因,并建议我纠正的方法。

<html>
<head>
    <!-- Jasmine References -->
    <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.3.3/jasmine.min.css">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.3.3/jasmine.min.js"></script>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.3.3/jasmine-html.min.js"></script>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.3.3/boot.min.js"></script>
    <!-- Angular and Angular Mock references -->
    <script type="text/javascript" src="https://code.angularjs.org/1.4.0-rc.2/angular.min.js"></script>
    <script type="text/javascript" src="https://code.angularjs.org/1.4.0-rc.2/angular-mocks.js"></script>
    <!-- The code we need to test -->
    <script type="text/javascript" src="/js/index.js"></script>
</head>
<body></body>
<script type="text/javascript">

    var app = angular.module('peoplesearchApp',[]);

    app.controller('peopleSearchCtrl',function($scope,$http){
        $scope.textChanged = function() {
            // obtain the list of user whose name have the given prefix
            $http.get('/findusers?q='+$scope.searchString.trim()).success(function(data, status) {
                $scope.users = data;
            }).error(function(data, status) {
                console.log("Error: could not retrieve users");
            });
        };
        // make an initial call to retrieve all users
        $scope.searchString = "";
        $scope.textChanged();
    });

    describe('search people app tests', function () {

        var $controller, $httpBackend, $scope;

        // setup before each test run
        beforeEach(module('peoplesearchApp'));
        beforeEach(inject(function (_$controller_, _$httpBackend_) {
            $controller = _$controller_;
            $scope = {};
            $httpBackend = _$httpBackend_;
        }));

        describe('only the users that have their names starting from the search query should be visible', function () {

            it('should show all users for a blank query', function () {
                $httpBackend.expectGET('/findusers?q=').respond(['Sean','Yaw','Lucy','Eric','Rory','Heyley']);
                $controller('peopleSearchCtrl', {$scope: $scope});
                $httpBackend.flush();
                expect($scope.users).toEqual(['Sean','Yaw','Lucy','Eric','Rory','Heyley']);
            });

            it('should show only Rory for query=r', function () {
                $httpBackend.expectGET('/findusers?q=r').respond(['Rory']);
                $controller('peopleSearchCtrl', {$scope: $scope});
                $httpBackend.flush();
                expect($scope.users).toEqual(['Rory']);
            });

        });

    })

</script>
</html>

编辑:问题是在第二个测试中,我想在发出假 http 请求之前以某种方式设置 $scope.searchString = "r"。我不知道该怎么做。

错误是:

Error: Unexpected request: GET /findusers?q=
Expected GET /findusers?q=r

代码笔:http://codepen.io/amarshanand/pen/MeJXdq

我看到的直接问题是,

beforeEach(inject(function(_$controller_, _$httpBackend_, _$rootScope_) {
    $controller = _$controller_;
    scope = _$rootScope_.$new();

您应该从 $rootScope 创建新范围。

更新:

如果这没有帮助,请分享您遇到的错误。

it('should show only Rory for query=r', function () {
    $httpBackend.expectGET('/findusers?q=').respond(['Sean','Yaw','Lucy','Eric','Rory','Heyley']);
    $httpBackend.expectGET('/findusers?q=r').respond(['Rory']);

    $controller('peopleSearchCtrl', {$scope: $scope});

    $scope.searchString = 'r';
    $scope.textChanged();    
    $httpBackend.flush();

    expect($scope.users).toEqual(['Rory']);
});

请检查这是否有帮助。

有效的代码笔 http://codepen.io/anon/pen/ezgjOx

稍微修改一下代码的设计

app.controller('peopleSearchCtrl',function($scope,$http){
          console.log($scope);  

          $scope.textChanged = function(_searched) {
                // obtain the list of user whose name have the given prefix
                $http.get('/findusers?q='+_searched.trim()).success(function(data, status) {
                    $scope.users = data;
                }).error(function(data, status) {
                    console.log("Error: could not retrieve users");
                });
            };
            // make an initial call to retrieve all users
            $scope.searchString = "";
            $scope.textChanged($scope.searchString);
        });

失败的测试现在正在运行:

it('should show only Rory for query=r', function () {     //faking the initialize call of the controller  
                  $httpBackend.expectGET('/findusers?q=').respond(['Sean','Yaw','Lucy','Eric','Rory','Heyley']);
                    $httpBackend.expectGET('/findusers?q=r').respond(['Rory']);
                    $controller('peopleSearchCtrl', {$scope: $scope});
                    $scope.textChanged('r');
                    $httpBackend.flush();
                    expect($scope.users).toEqual(['Rory']);
                });

工作代码笔:http://codepen.io/gpincheiraa/pen/pbRKMZ

我在随附的代码中发现了几个问题: 1. 您为每个不正确的测试实例化 $controller。控制器应该在顶层实例化,我们应该在需要的地方使用该控制器实例。这样我们就可以减少代码重复,提高测试执行时间。

  1. 您已添加$scope.searchString = ""; $scope.textChanged(); 执行之前的行;从编码的角度来看,这看起来不太好。在 textChanged() 本身中,我们应该检查 $scope.searchString 是否为空白或未定义,并据此创建 Rest URL。

  2. 在第二个测试中,我们必须将以下几行放在开头: httpBackend.when('GET', '/findusers?q=') .respond(['Sean','Yaw','Lucy','Eric','Rory','Heyley']);否则它会抱怨 /findusers?q= url

我稍微修改了上面的代码,现在可以使用了:

<html>
<head>
    <!-- Jasmine References -->
    <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.3.3/jasmine.min.css">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.3.3/jasmine.min.js"></script>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.3.3/jasmine-html.min.js"></script>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.3.3/boot.min.js"></script>
    <!-- Angular and Angular Mock references -->
    <script type="text/javascript" src="https://code.angularjs.org/1.4.0-rc.2/angular.min.js"></script>
    <script type="text/javascript" src="https://code.angularjs.org/1.4.0-rc.2/angular-mocks.js"></script>
</head>
<body></body>
<script type="text/javascript">

    var app = angular.module('peoplesearchApp',[]);

    app.controller('peopleSearchCtrl',function($scope,$http){
        $scope.textChanged = function() {
            // obtain the list of user whose name have the given prefix
            var searchUsers = ($scope.searchString) ? $scope.searchString.trim(): "";

            $http.get('/findusers?q=' + searchUsers).success(function(data, status) {
                $scope.users = data;
            }).error(function(data, status) {
                console.log("Error: could not retrieve users");
            });

        };
        // make an initial call to retrieve all users
        $scope.textChanged();
    });

    describe('search people app tests', function () {

        var controller, httpBackend, scope;

        // setup before each test run
        beforeEach(module('peoplesearchApp'));
        beforeEach(inject(function (_$controller_, _$httpBackend_, _$rootScope_) {
            scope = _$rootScope_.$new();
            httpBackend = _$httpBackend_;

            controller = _$controller_('peopleSearchCtrl', {$scope: scope});
        }));

        describe('only the users that have their names starting from the search query should be visible', function () {

            it('should show all users for a blank query', function () { 
                httpBackend.when('GET', '/findusers?q=').respond(['Sean','Yaw','Lucy','Eric','Rory','Heyley']);

                scope.textChanged();
                httpBackend.flush();
                expect(scope.users).toEqual(['Sean','Yaw','Lucy','Eric','Rory','Heyley']);
            });

            it('should show only Rory for query=r', function () {
                httpBackend.when('GET', '/findusers?q=')
                        .respond(['Sean','Yaw','Lucy','Eric','Rory','Heyley']);

                scope.searchString = 'r'; 

                httpBackend.when('GET', '/findusers?q=r')
                        .respond(['Rory']);
                scope.textChanged();
                httpBackend.flush();
                expect(scope.users).toEqual(['Rory']);
            });
        });

    })

</script>
</html>

希望能解决您的问题。

干杯!