Jul*_*els 5 javascript jasmine angularjs keycloak
我正在尝试为使用 Keycloak 进行身份验证的 Angular 应用程序编写一个测试套件。
但是,由于 Keycloak 要求您手动引导 Angular 并设置一些拦截器,因此由于以下错误,我无法启动任何测试:
Error: $injector:unpr
Unknown Provider: AuthProvider <- Auth <- authInterceptor <- $http <- $templateRequest <- $route
Run Code Online (Sandbox Code Playgroud)
这是引发错误的拦截器的代码:
angular.module('MPMReportGenerator')
.factory('authInterceptor', function authInterceptor ($q, Auth, $log) {
return {
request: function (config) {
var deferred = $q.defer()
Auth.updateToken(5).success(function () {
config.headers = config.headers || {}
config.headers.Authorization = 'Bearer ' + Auth.token
deferred.resolve(config)
}).error(function () {
deferred.reject('Failed to refresh token')
})
$log.info(deferred.promise)
return deferred.promise
}
}
})
Run Code Online (Sandbox Code Playgroud)
我的想法是我应该模拟拦截器并让它返回请求。但是,我不知道如何做到这一点,因为这个拦截器永远不会作为依赖项注入任何地方,它只是用上面的块声明,就是这样。我对模拟服务的理解是它们需要注入到某个地方才能被模拟。
我在 Angular 中的 Keycloak 实现直接来自他们的示例(如果有帮助的话)。
我一直在尝试将模拟的 Auth 模块注入到我正在为其编写测试的服务中,但仍然没有任何变化。
一般来说,我对单元测试非常陌生,所以我在尝试追踪这一点时有点迷失。我觉得我知道问题出在哪里,但不知道如何解决它(在应用程序的引导过程中添加了身份验证服务,我需要模拟它才能工作,但似乎我不知道如何/在哪里正确地嘲笑它)
这是整个测试代码:
describe('Services', function () {
'use strict'
beforeEach(module('MPMReportGenerator'))
module(function ($provide) {
$provide.factory('Auth', function () {
return null
})
})
var sectionService, $httpBackend, mockAuth
beforeEach(inject(function (_sectionService_, _$httpBackend_, Auth) {
sectionService = _sectionService_
$httpBackend = _$httpBackend_
mockAuth = Auth
}))
it('should get sections', function () {
$httpBackend.expect('GET', '/MPMReportGenerator/api/categories/all').respond(200)
sectionService.getSections()
expect($httpBackend.flush).not.toThrow()
})
})
Run Code Online (Sandbox Code Playgroud)
我通过制作 Auth 的模拟版本成功地克服了最初的错误。
我现在在实现 Keycloak 的 Javascript 库的模拟版本时遇到问题。
我当前的模拟代码如下:
beforeEach(module(function ($provide) {
$provide.factory('Auth', function ($q) {
return {
updateToken: function (minValidity) {
return {
success: function (fn) {
var deferred = $q.defer()
deferred.resolve('')
fn(deferred.promise)
},
error: function (fn) {
var deferred = $q.defer()
deferred.resolve('Error')
fn(deferred.promise)
}
}
},
token: 'thisisafaketokenfortesting'
}
})
}))
Run Code Online (Sandbox Code Playgroud)
并抛出这个错误:
Expected function not to throw, but it threw TypeError: undefined is not an object (near '...}).error(function () {...').
target/MPMReportGenerator-1.0.0/js/app.service.spec.js:42:43
loaded@http://localhost:9876/context.js:151:17
Run Code Online (Sandbox Code Playgroud)
我的实际测试是这样的:
it('should get sections', function () {
$httpBackend.expect('GET', '/MPMReportGenerator/api/categories/all').respond(200)
sectionService.getSections()
expect($httpBackend.flush).not.toThrow()
})
Run Code Online (Sandbox Code Playgroud)
我终于弄明白了。
如果有人想使用 keycloak 测试 Angular 应用程序,以下是所需的代码:
beforeEach(
module(function ($provide) {
$provide.factory('Auth', function ($q) {
return {
updateToken: function (minValidity) {
return {
success: function () {
return {
error: function () {
var deferred = $q.defer()
return deferred.promise
}
}
}
}
},
token: 'thisisafaketokenfortesting'
}
})
}))
Run Code Online (Sandbox Code Playgroud)
请注意,如果您打算测试官方示例中提供的拦截器,您可能需要模拟 keycloak 库的其他部分。
不要使用上面的代码,下面的代码效果更好:
$provide.factory('Auth', function () {
return {
updateToken: function (minValidity) {
return {
success: function () {
return this
},
error: function () {
return this
}
}
},
token: 'thisisafaketokenfortesting'
}
})
Run Code Online (Sandbox Code Playgroud)