这是我的 Controller 的一部分:
$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();
});
});
但是测试总是失败(预期为 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关于冲洗。
关于javascript - 如何在 AngularJS 中使用 $http.jsonp 对函数进行单元测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24293643/