测试AngularJs'$ http.defaults.headers.common如果特定的标头设置测试、AngularJs、http、headers

2023-09-13 03:25:37 作者:心悦君兮君不知

所以,我是新来的JavaScript和AngularJS的世界,并为此我的code是不如它应该是还没有,但它的改进。不过我开始学习和实施一个REST后端简单的登录页面。登录表格提交后,一个认证令牌返回并设置为这样一个默认的HTTP标头属性。

  $ http.defaults.headers.common ['X-AUTH-TOKEN'] = data.authToken; 

这工作得很好,只要我手动测试,但这并不是去,所以我想实现一个单元测试如果X-AUTH-TOKEN头设置哪些检查方法。

有没有一种方法来检查以$ httpBackend?例如我有以下测试:

 描述('的LoginController',函数(){    VAR范围,CTRL $ httpBackend;    //每次测试之前加载我们的应用程序模块定义。    beforeEach(模块('对myApp'));    //喷油器会忽略前导和尾随下划线的位置(即_ $ httpBackend_)。    //这使我们能够注入一个服务,但然后将其附加到一个变量    具有相同名称作为服务//。    beforeEach(注(功能(_ $ httpBackend_,$ rootScope,$控制器){        $ httpBackend = _ $ httpBackend_;        范围= $ rootScope $新的()。        CTRL = $控制器('的LoginController',{$适用范围:适用范围},{$ HTTP:$ httpBackend},{$位置:空});    }));    它('应该创建一个包含authToken并设置',函数(){        $ httpBackend.expectPOST(的http://本地主机:9000 /登录','200')响应(200,{的authToken:52d29fd63004c92b972f6b99; 65e922bc-5e33-4bdb-9d52-46fc352189fe}')。        scope.login('200');        $ httpBackend.flush();        期待(scope.data.authToken).toBe('52d29fd63004c92b972f6b99; 65e922bc-5e33-4bdb-9d52-46fc352189fe');        期待(scope.loginValidationOverallError).to​​Be(假);        期待(scope.status).toBe(200);    }); 

我的控制器看起来是这样的:

  .controller('的LoginController',['$范围,$ HTTP,$位置',    功能($范围,$ HTTP,$位置){        //登录的东西        $ scope.data = {};        $ scope.status = {};        $ scope.loginValidationOverallError = FALSE;        $ scope.login =功能(用户){            $ http.post(的http://本地主机:9000 /登录,用户).success(功能(数据,状态){                $ scope.data =数据;                $ scope.status =状态;                $ scope.loginValidationOverallError = FALSE;                的console.log($ scope.status,$ scope.data);                $ http.defaults.headers.common ['X-AUTH-TOKEN'] = data.authToken;                $ location.path('/用户);            })错误(功能(数据,状态){                    的console.log(状态+'错误');                    $ scope.loginValidationOverallError =真;                });        };        ... 
AngularJs单元测试

我检查在 http://docs.angularjs.org/api/ngMock的文档。 $ httpBackend 但如果最后的测试实际上是适用于我的code(以及如何code实际上测试的东西)

我不知道

 它('应该发送AUTH头',函数(){    VAR控制器= createController();    $ httpBackend.flush();    $ httpBackend.expectPOST('/ add-msg.py',未定义功能(头){        //检查头球攻门被发送,如果它不是预期不会        //匹配要求和测试将失败        返回头['授权'] =='XXX';    })响应(201,'');    $ rootScope.saveMessage('不管');    $ httpBackend.flush();}); 

解决方案

我面临着同样的问题,我终于解决了。这是非常棘手的。

周守军code对于 AuthenticationService.login()功能

  $ http.post(...)  .success(功能(数据){     ...     $ http.defaults.headers.common ['授权'] = data.oauth_token;   }); 

测试code

  beforeEach(注(功能(_ $ httpBackend_,的AuthenticationService){  $ httpBackend = _ $ httpBackend_;  $ =的AuthenticationService的AuthenticationService;}));它('应以正确的参数登录成功,注入(函数($ HTTP){//鉴于......VAR fakeResponse = {  的access_token:'即为MyToken}$ httpBackend.expectPOST('的OAuth /令牌',urlEn codedParams,功能(头){      返回头['内容类型'] ===应用程序/ x-WWW的形式urlen $ C $光盘';})响应(200,fakeResponse)。// 什么时候$ authenticationService.login(用户名,密码);// 然后$ httpBackend.flush();期待($ http.defaults.headers.common ['授权'])TOBE('即为MyToken')。 

在招这里要说的是默认的头被设置在 $实HTTP服务,而不是嘲笑$ httpBackend。这就是为什么你要注入真正的$ http服务

我试着测试$ httpBackend却得到了一个不确定的错误,因为$ httpBackend没有'缺省'属性。

So I'm new to the world of JavaScript and AngularJS and therefor my code is not as good as it should be yet, but it's improving. Nevertheless I started learning and implementing a simple login page with a REST Backend. After the Login-Form is submitted, a authentication-token is returned and set as a default http-header property like this

$http.defaults.headers.common['X-AUTH-TOKEN'] = data.authToken;

This works fine whenever I test it manually, but that's not the way to go so I'd like to implement a unit-test which checks if the X-AUTH-TOKEN header is set.

Is there a way to check that with $httpBackend? e.g I have the following test:

describe('LoginController', function () {
    var scope, ctrl, $httpBackend;

    // Load our app module definition before each test.
    beforeEach(module('myApp'));

    // The injector ignores leading and trailing underscores here (i.e. _$httpBackend_).
    // This allows us to inject a service but then attach it to a variable
    // with the same name as the service.
    beforeEach(inject(function (_$httpBackend_, $rootScope, $controller) {
        $httpBackend = _$httpBackend_;
        scope = $rootScope.$new();
        ctrl = $controller('LoginController', {$scope: scope}, {$http: $httpBackend}, {$location: null});
    }));

    it('should create an authToken and set it', function () {
        $httpBackend.expectPOST('http://localhost:9000/login', '200').respond(200, '{"authToken":"52d29fd63004c92b972f6b99;65e922bc-5e33-4bdb-9d52-46fc352189fe"}');
        scope.login('200');
        $httpBackend.flush();

        expect(scope.data.authToken).toBe('52d29fd63004c92b972f6b99;65e922bc-5e33-4bdb-9d52-46fc352189fe');
        expect(scope.loginValidationOverallError).toBe(false);
        expect(scope.status).toBe(200);
    });

My Controller looks like this:

.controller('LoginController', ['$scope', '$http', '$location',
    function ($scope, $http, $location) {

        // Login Stuff
        $scope.data = {};
        $scope.status = {};
        $scope.loginValidationOverallError = false;
        $scope.login = function (user) {
            $http.post('http://localhost:9000/login', user).success(function (data, status) {

                $scope.data = data;
                $scope.status = status;
                $scope.loginValidationOverallError = false;


                console.log($scope.status, $scope.data);
                $http.defaults.headers.common['X-AUTH-TOKEN'] = data.authToken;
                $location.path('/user');

            }).error(function (data, status) {
                    console.log(status + ' error');
                    $scope.loginValidationOverallError = true;
                });

        };
        ...

I checked the documentation at http://docs.angularjs.org/api/ngMock.$httpBackend but am not sure if the last test is actually applicable to my code (and how that code actually tests something)

it('should send auth header', function() {
    var controller = createController();
    $httpBackend.flush();

    $httpBackend.expectPOST('/add-msg.py', undefined, function(headers) {
        // check if the header was send, if it wasn't the expectation won't
        // match the request and the test will fail
        return headers['Authorization'] == 'xxx';
    }).respond(201, '');

    $rootScope.saveMessage('whatever');
    $httpBackend.flush();
});

解决方案

I was facing the same issue and I finally solved it. It was very tricky

Souce code for AuthenticationService.login() function

$http.post(...)
  .success(function(data) {
     ...
     $http.defaults.headers.common['Authorization'] = data.oauth_token;
   });

Test code

beforeEach(inject(function(_$httpBackend_,AuthenticationService) {
  $httpBackend = _$httpBackend_;
  $authenticationService = AuthenticationService;
}));

it('should login successfully with correct parameter', inject(function($http) {
// Given
...
...
var fakeResponse = {
  access_token: 'myToken'
}

$httpBackend.expectPOST('oauth/token',urlEncodedParams, function(headers) {
      return headers['Content-Type'] ===  'application/x-www-form-urlencoded';
}).respond(200, fakeResponse);

// When
$authenticationService.login(username,password); 


// Then
$httpBackend.flush();
expect($http.defaults.headers.common['Authorization']).toBe('myToken');

The trick here is that the default header is set on the real $http service, not the mocked $httpBackend. That's why you should inject the real $http service

I've tried testing the $httpBackend but got an "undefined" error because $httpBackend does not have 'defaults' property