这是我的控制器的一部分:
$scope.isLoggedIn = function () {
return Boolean($sessionStorage.isLoggedIn);
};
$scope.login = function () {
//If the browser fills in the username and password field then angular's model will not be updated so we need
//to manually pull them out of the DOM :(. See this issue for details: https://github.com/angular/angular.js/issues/1460
var username = $('#usernameInput').val();
var password = $('#passwordInput').val();
$scope.loginErrMsg = null;
$http.jsonp("http://ldap-auth.otpp.me" + '/login?callback=JSON_CALLBACK&username=' + encodeURIComponent(username) + '&password=' + encodeURIComponent(password))
.success(function (data, isLoggedIn) {
// This app is for internal use only, security is not a major concern.
// So using sessionStorage to store the login status is OK.
$sessionStorage.displayName = data.displayName;
$sessionStorage.isLoggedIn = true;
})
.error(function () {
$scope.loginErrMsg = "Invalid username or password";
});
};
这是我的测试:
describe('Controller: MainCtrl', function () {
// load the controller's module
beforeEach(module('uiappApp'));
var MainCtrl,
$httpBackend,
scope;
// Initialize the controller and a mock scope
beforeEach(inject(function ($injector, $controller, $rootScope) {
scope = $rootScope.$new();
MainCtrl = $controller('MainCtrl', {
$scope: scope
});
$httpBackend = $injector.get('$httpBackend');
}));
it('should login', function () {
var isLoggedIn = scope.isLoggedIn();
expect(isLoggedIn).toBe(false);
var username = $('<input type="text" id="usernameInput"/>');
var password = $('<input type="text" id="passwordInput"/>');
$('body').html('<div>')
.find('div')
.append(username)
.append(password);
username.val('username');
password.val('password');
var response = $httpBackend.expectJSONP('http://ldap-auth.otpp.me/login?callback=JSON_CALLBACK&username=username&password=password');
response.respond({displayName: 'userX'}, {'A-Token': 'xxx'});
scope.login();
expect(scope.isLoggedIn()).toEqual(true);
$('body').empty();
});
});
但是,测试始终会失败(
Expected false to equal true.
)。看来我没有让$ httpBackend工作。但是我不知道哪里出了问题。基本上,我想在单元测试时模拟$ http.jsonp()响应以提供模拟的json,然后测试用户登录。非常感谢您的帮助!
@HackedByChinese在您迈出第一步之后,我得到了:
it('should login', function () {
var isLoggedIn = scope.isLoggedIn();
expect(isLoggedIn).toBe(false);
var username = $('<input type="text" id="usernameInput"/>');
var password = $('<input type="text" id="passwordInput"/>');
$('body').html('<div>')
.find('div')
.append(username)
.append(password);
username.val('username');
password.val('password');
var response = $httpBackend.expectJSONP('http://ldap-auth.otpp.me/login?callback=JSON_CALLBACK&username=username&password=password');
response.respond({displayName: 'userX'}, {'A-Token': 'xxx'});
scope.login();
$httpBackend.flush();
expect(scope.isLoggedIn()).toEqual(true);
$('body').empty();
});
但是我收到以下错误消息:
Error: Unexpected request: GET views/main.html
No more request expected
at $httpBackend (C:/repo/docserver-ui/UIApp/app/bower_components/angular-mocks/angular-mocks.js:1177:9)
at sendReq (C:/repo/docserver-ui/UIApp/app/bower_components/angular/angular.js:7967:9)
at $get.serverRequest (C:/repo/docserver-ui/UIApp/app/bower_components/angular/angular.js:7708:16)
at deferred.promise.then.wrappedCallback (C:/repo/docserver-ui/UIApp/app/bower_components/angular/angular.js:11100:81)
at deferred.promise.then.wrappedCallback (C:/repo/docserver-ui/UIApp/app/bower_components/angular/angular.js:11100:81)
at C:/repo/docserver-ui/UIApp/app/bower_components/angular/angular.js:11186:26
at Scope.$get.Scope.$eval (C:/repo/docserver-ui/UIApp/app/bower_components/angular/angular.js:12175:28)
at Scope.$get.Scope.$digest (C:/repo/docserver-ui/UIApp/app/bower_components/angular/angular.js:12004:31)
at Function.$httpBackend.flush (C:/repo/docserver-ui/UIApp/app/bower_components/angular-mocks/angular-mocks.js:1435:16)
at null.<anonymous> (C:/repo/docserver-ui/UIApp/test/spec/controllers/main.js:43:22)
Process finished with exit code 0
这是我的部分html:
<form class="navbar-form navbar-right" role="form" ng-show="!isLoggedIn()">
<p class="navbar-text" id="loginErrMsg">{{loginErrMsg}}</p>
<div class="form-group">
<input type="text" placeholder="User Name" id="usernameInput"
class="form-control"
ng-class="{'error-fields': loginErrMsg}">
</div>
<div class="form-group">
<input type="password" placeholder="Password" id="passwordInput" class="form-control" ng-class="{'error-fields': loginErrMsg}">
</div>
<button type="submit" class="btn btn-success" ng-click="login()">Sign in</button>
</form>
最佳答案
在调用scope.login()
之后,在expect(...)
之前,您需要调用$httpBackend.flush()
使其响应以指定的期望值。
这不是特定于JSONP,而是通常对单元测试$http
进行调用。
总结一下,这是对发出$http
请求的代码进行单元测试的步骤:
使用$httpBackend
设置您的期望。
调用进行$http
调用的代码。
调用$httpBackend.flush()
,使其以您设置的期望响应任何未决请求。
进行测试断言。
有关刷新,请参见docs。