为 angular REST 应用编写测试

Write tests for an angular REST app

到目前为止我一直一无所知。假设我有这个非常简单的应用程序模块:

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

app.service('searchService',  ['$http', function($http){
    var baseURL="https://someonehost.com/product/search&query=";
    return  {
        search: function(query){
            return  $http.get(baseURL+query);
        }
    };
}]);

app.controller('mainCtrl', ['$scope','searchService',function($scope, searchService) {
  searchService.search($scope.searchWords).success(function(data) {
        $scope.responseData=data;
  });   
}]);

它适用于浏览器。现在我尝试使用 karma、mocha 和 chai 对其进行测试。假设我想写一个测试用例来测试请求的成功路径。我应该怎么写呢?到目前为止,这是我正在尝试的:

describe('',function(){
    var $httpBackend = null;
    var locationService = null;
    var baseURL="https://someonehost.com/product/search&query=";

    beforeEach(function(){
        module('myApp');
        inject(function(_$httpBackend_,_locationService_){
            $httpBackend    =   _$httpBackend_;
            locationService =   _locationService_;
        });
    });

    it('test case 1',function(){
        var searchWord = 'car';
        $httpBackend.when('GET',baseURL+searchWord).respond(200,'');
        $httpBackend.expectGET(baseURL+searchWord);
        searchService.search(searchWord).success(function(data) {
          console.log('data: '+data);
        });
        $httpBackend.flush();
    });

});

但是它 returns 没有数据,它应该在控制台中:

LOG: 'data: '
Firefox 37.0.0 (Ubuntu): Executed 1 of 1 SUCCESS (0.033 secs / 0.006 secs)

默认情况下,Angular 在单元测试期间不接受外部服务的 $http。您应该为假数据提供模拟并且只测试代码的完整性。

您要做的不是单元测试而是集成测试,几周前我遇到了完全相同的问题。我发现这个文件覆盖了 ngMocks 并执行了正常的查询。

https://gist.github.com/kyro38/3371aaac54bf6583852f

在您的 Karma/Mocha/WhatEver 测试配置中,您在 angular 之后导入它(下面的示例是针对 Karma 的):

// Karma configuration
module.exports = function (config) {
config.set({

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: './',

    // frameworks to use
    // some available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['jasmine', 'chai'],

    // list of files / patterns to load in the browser
    files: [
        './bower_components/jquery/dist/jquery.js',
        './bower_components/angular/angular.js',
        './src/client/test-helpers/angular-mocks-with-real-backend.js', [...]

然后你就可以运行你想要的测试了。如果有任何问题,请告诉我。

不要忘记让你的测试异步 ;)

https://jasmine.github.io/edge/introduction.html#section-Asynchronous_Support

小心 $httpBackend

如文档中所述:

Fake HTTP backend implementation suitable for unit testing applications that use the $http service.

尝试改用 $http。

it('should get nok 8 one single contact', function(done) {
    var promise = $http({
        method: 'get',
        url: baseurl + '/contact/list',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
            'Accept': '*/*'
        },
        params: {
            nokid: 8
        }
    });
    promise.then(function(result) {
        expect(result.status).toEqual(200);
    }, function(error) {
        expect(error.status).toEqual(200);
    }).
    finally(done);
});

https://docs.angularjs.org/api/ngMock/service/$httpBackend#!

最后提示:在您当前的测试中,您给 expectGET 一个错误的 url :

var searchWord = 'car';
$httpBackend.expectGET(searchWord);

我会试试这个

it('test case 1',function(done){
    $http({
        method: 'get',
        url: baseURL + 'car',
        ...
    }).then(function (success) {
        console.log('data: ' + success.data);
        done(); // stop test from waiting
    }, function (fail) {
        console.log('data: ' + fail);
        done(); // stop test from waiting
    });
});