- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有这两个服务文件,其中一个包含在另一个中。
app.service.ts
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { throwError, Observable } from 'rxjs';
import { catchError, map } from 'rxjs/operators';
import { Router } from '@angular/router';
import { environment } from '../../environments/environment';
import { AuthService } from '../_services/auth.service';
@Injectable({
providedIn: 'root'
})
export class AppService {
protected _apiURL = environment.apiURL;
// Define URLs here
_overviewURL: string;
_deleteUserUrl: string;
constructor(private http: HttpClient,
private _router: Router,
private _authService: AuthService) {
this.setApiUrl();
}
/* Begin: Misc services */
/**
* @description Sets the header for each request
* @param authorize Flag to whether include authorization token in headers or not
* @returns - Header consisting of Authorization token & Content-type
*/
setHeaders(authorize: boolean = false) {
const headers: any = {};
headers['Content-Type'] = 'application/json';
if (authorize && this._authService.isAuthenticated()) {
const authenticated = this._authService.getAuthenticatedUser();
headers.Authorization = `Bearer ${authenticated.idToken}`;
}
return {
headers: new HttpHeaders(headers)
};
}
/**
* @description Sets all the service URLs with the respective endpoints
*/
setApiUrl() {
this._overviewURL = this._apiURL + 'overview';
this._deleteUserUrl = this._apiURL + 'user/delete';
}
/**
* @description Gets the user overview page details based on BGtOccName & BGtID
* @param params - consists of BGtOccName & BGtId (BG Occupation Name & BG Occupation ID).
* Refer BG Docs: https://dev.burning-glass.com/docs/versions/3.3/getting-started
*/
getOverviewPageInfo(params: any) {
return this.http.post(this._overviewURL, params, this.setHeaders())
.pipe(
map(this.handleResponse),
catchError(this.handleError)
);
}
/**
* @description Delete an authenticated user
* @param user User object from localStorage
*/
deleteUser(user: any) {
return this.http.post(this._deleteUserUrl, user, this.setHeaders(true))
.pipe(
map(this.handleResponse),
catchError(this.handleError)
);
}
/**
* @description processes observable response
* @param res - takes in the response object
* @returns - data object
*/
private handleResponse = (res: any) => {
return res.data || {};
}
/**
* @description processes observable error
* @param error - takes in the error object
* @returns - error object
*/
private handleError = (error: Response | any) => {
console.error(error.error.message || error.message);
const errorMsg = error.error.message || error.message;
if (errorMsg === 'Invalid token') { this._router.navigate(['/login']); localStorage.removeItem('loggedUser'); }
return throwError(error.error.error);
}
}
auth.service.ts
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { environment } from '../../environments/environment';
import * as auth0 from 'auth0-js';
import { ToastrService } from 'ngx-toastr';
@Injectable({
providedIn: 'root'
})
export class AuthService {
private _idToken: string;
private _accessToken: string;
private _expiresAt: number;
private auth0User: any;
auth0 = new auth0.WebAuth({
clientID: environment.AUTH0_CLIENTID,
domain: environment.AUTH0_DOMAIN,
responseType: 'token id_token',
redirectUri: environment.AUTH0_REDIRECT_URI
});
constructor( public router: Router,
private _toastr: ToastrService) {
this.auth0User = JSON.parse(localStorage.getItem('auth0User'));
this._idToken = (this.auth0User && this.auth0User.idToken) ? this.auth0User.idToken : '';
this._accessToken = (this.auth0User && this.auth0User.accessToken) ? this.auth0User.accessToken : '';
this._expiresAt = (this.auth0User && this.auth0User.expiresAt) ? this.auth0User.expiresAt : 0;
}
get accessToken(): string {
return this._accessToken;
}
get idToken(): string {
return this._idToken;
}
public login(): void {
this.auth0.authorize();
}
public handleAuthentication(): void {
this.auth0.parseHash((err, authResult) => {
if (authResult && authResult.accessToken && authResult.idToken) {
this.localLogin(authResult);
this.router.navigate(['/home']);
this._toastr.success(`You have been logged in!`, `Success`);
} else if (err) {
this.router.navigate(['/home']);
this._toastr.error(`Invalid login`, `Failed`);
}
});
}
private localLogin(authResult): void {
// Set the time that the access token will expire at
const expiresAt = (authResult.expiresIn * 1000) + Date.now();
this._accessToken = authResult.accessToken;
this._idToken = authResult.idToken;
this._expiresAt = expiresAt;
let auth0User: any = localStorage.getItem('auth0User');
if (auth0User) {
auth0User = JSON.parse(auth0User);
auth0User.idToken = authResult.idToken;
auth0User.expiresAt = expiresAt;
auth0User.accessToken = authResult.accessToken;
localStorage.setItem('auth0User', JSON.stringify(auth0User));
} else {
localStorage.setItem('auth0User', JSON.stringify({
idToken: authResult.idToken,
expiresAt: expiresAt,
accessToken: authResult.accessToken,
idTokenPayload: authResult.idTokenPayload
}));
}
}
public renewTokens(): void {
this.auth0.checkSession({}, (err, authResult) => {
if (authResult && authResult.accessToken && authResult.idToken) {
this.localLogin(authResult);
} else if (err) {
this._toastr.error(`Could not get a new token (${err.error}: ${err.error_description}).`, `Failed`);
this.logout();
}
});
}
public logout(): void {
// Remove tokens and expiry time
this._accessToken = '';
this._idToken = '';
this._expiresAt = 0;
localStorage.removeItem('auth0User');
this.auth0.logout({
returnTo: window.location.origin
});
this._toastr.success(`You have been logged out!`, `Success`);
}
public isAuthenticated(): boolean {
// Check whether the current time is past the
// access token's expiry time
return this._accessToken && Date.now() < this._expiresAt;
}
public getAuthenticatedUser() {
if (localStorage.getItem('auth0User')) {
return JSON.parse(localStorage.getItem('auth0User'));
} else {
return null;
}
}
}
每当我运行我的 app.service.spec.ts 测试文件时,它都会抛出与任何代码无关的错误。
app.service.spec.ts
import { TestBed } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { AppService } from './app.service';
describe('AppService', () => {
let service: AppService;
let httpMock: HttpTestingController;
beforeEach(() => TestBed.configureTestingModule({
imports: [
HttpClientTestingModule,
RouterTestingModule
],
providers: [AppService]
}));
beforeEach(() => {
service = TestBed.get(AppService);
httpMock = TestBed.get(HttpTestingController);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
afterEach(() => {
httpMock.verify();
});
it('should retrieve overview details', () => {
const postParams = {
'designation': 'Fire Chief / Marshal',
'id': '378'
};
const overviewDetails = {
'data': {
'highSalary': 115511.77,
'estimatedSalary': 98935,
'nationalSalary': 98498.34,
'skills': [
{
'name': 'JavaScript Object Notation (JSON)',
'description': 'In computing, JavaScript Object Notation or JSON ( JAY-sn), is an open-standard ' +
'file format that uses human-readable text to transmit data objects consisting of' +
'attributevalue pairs and array data types (or any other serializable value).',
'count': 45084
},
{
'name': 'Software Architecture',
'description': 'Software architecture refers to the high level structures of a software system,' +
'the discipline of creating such structures, and the documentation of these structures.',
'count': 42676
}
],
'careers': [
{
'name': 'Chief Executive Officer',
'meanSalaryDiff': 11347.74
},
{
'name': 'Database Architect',
'meanSalaryDiff': 7699.84
}
]
}
};
service.getOverviewPageInfo(postParams).subscribe(overview => {
expect(overview).toEqual(overviewDetails.data);
});
const req = httpMock.expectOne(service._overviewURL);
expect(req.request.method).toBe('POST');
req.flush(overviewDetails);
});
});
但是如果删除这些行
if (authorize && this._authService.isAuthenticated()) {
const authenticated = this._authService.getAuthenticatedUser();
headers.Authorization = `Bearer ${authenticated.idToken}`;
}
从 app.service.ts 文件,然后所有测试工作正常(如您所见,它正在调用 authService 函数)。
我曾尝试将 authService 包含到 app.service.spec.ts 的提供者中,如下所示,但没有成功。 :(
beforeEach(() => TestBed.configureTestingModule({
imports: [
HttpClientTestingModule,
RouterTestingModule
],
providers: [AppService, AuthService]
}));
我的问题:如何在另一个可注入(inject)文件中包含/测试一个可注入(inject)(服务)?
最佳答案
我认为你需要为它提供一个模拟,除非你想做一个集成测试。例如,您尝试通过在 providers: [...]
列表中包含 AuthService
来修复它的方式将不起作用,除非您还添加了必要的文件构建您的 AuthService
(即,您需要将 ToastrService
添加到您的提供者列表中。
我的建议是通过告诉 TestBed
使用您的模拟而不是实际的 AuthService
来模拟测试中的 AuthService
。这是我所拥有的并且它通过了测试:
// in app.service.spec.ts
//imports
describe('AppService', () => {
let service: AppService;
let httpMock: HttpTestingController;
// Add your mock and all the methods/values you need.
// You can Spy on this object if you need to change the return values
// for different tests
let mockAuthSerice: any = {
isAuthenticated: () => true,
getAuthenticatedUser: () => {
return { user: 'bob', idToken: 'token' }
},
};
beforeEach(() => TestBed.configureTestingModule({
imports: [
HttpClientTestingModule,
RouterTestingModule
],
// Provide AuthServide but tell Angular to use the mock instead
providers: [
AppService,
{ provide: AuthService, useValue: mockAuthSerice }
]
}));
// ...rest of test file
});
关于angular - [ Angular 7+] : How to unit test a service inside another service spec?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56221666/
我有以下功能: fun process(t: T, call: (U) -> Unit, map: (T) -> U) = call(map(t)) fun processEmpty(t: T,
关闭。这个问题需要更多focused .它目前不接受答案。 想改善这个问题吗?更新问题,使其仅关注一个问题 editing this post . 4年前关闭。 Improve this questi
我正在实现 SVG Tiny 1.1,但我无法理解“用户单元”的概念。 SVG 1.1 规范将每个没有指定单位(例如“mm”、“cm”、“pt”等)的 定义为“用户单位”。 在实现接口(interfa
我正在学习本教程 - http://blog.dasberg.nl/getting-your-frontend-code-quality-in-order/ - 将前端质量指标推送到 SonarQub
我用了 rails new app --skip-test-unit 因为最初,我认为我可以稍后添加测试。 我开发了我的应用程序的很大一部分。 现在,我想添加 Test::Unit 但我找不到任何有关
您如何对由某些报表引擎(例如Crystal Reports或SQL Server Reporting Services)创建的报表进行“单元测试”? 最佳答案 报告的问题类似于GUI的问题。 如果报表
今天在 Proggit 上,我正在阅读题为“Why Unit Testing Is A Waste of Time”的提交的评论线程。 我并不真正关心文章的前提,而是关心 comment对此作出: T
“单元测试”属于白盒测试还是黑盒测试?还是与其他两种测试完全不同? 最佳答案 我觉得这个article by Kent Beck更多地引用 TDD 和单元测试很好地总结了这一点。基本上,这取决于您实际
这是代码: def filterAcc(p: Tweet => Boolean, acc: TweetSet): TweetSet = { foreach(tweet => if(p(el
我打算编写一个抽象类来测试我所有的 DTO 和 DOMAIN 对象。此类将采用可模板对象(通用类型)并使用反射来获取其中的属性类型,并将一些默认值分配给标识的原始类型,稍后将通过访问它们来断言这些类型
我有一个像这样的简单容器特征: trait Handler { def apply[In, Out](in: In): Out } 当我尝试实现它时: new Handler { def ap
为什么这样编译 scala> import scala.concurrent.Future import scala.concurrent.Future scala> val f: Unit = Fu
您使用什么样的实践来使您的代码对单元测试更加友好? 最佳答案 TDD——首先编写测试,强制你要考虑可测试性和帮助编写实际的代码需要的,而不是你认为可能的需要 接口(interface)重构——使得 m
我在elasticsearch中有文本字段,我想在kibana上可视化词云... 第一步,我们需要标记它们,我使用了“标准标记器” ... 使用这种形式的词云可视化结果如下图所示: 但是我需要的是专有
我有以下方法: override def insertAll(notifications: Seq[PushNotificationEncoded]) (i
我的应用程序服务层中有很多方法正在做这样的事情: public void Execute(PlaceOrderOnHoldCommand command) { var order = _rep
一直在使用 Sails.js,但在为 Controller 设计 Jasmine 单元测试时遇到了麻烦。如果这很明显,请原谅我的无知,因为在过去的 3-4 个月里我才深入研究 JavaScript 开
Closed. This question does not meet Stack Overflow guidelines。它当前不接受答案。 想改善这个问题吗?更新问题,以便将其作为on-topic
在ReKotlin repo README中,有如下代码: data class CounterActionIncrease(val unit: Unit = Unit): Action 代码Unit
我想对一个业务类进行测试,但我遇到了这个问题:其中一个模拟对象与其他类(例如 Sites、URL 和 ComplexObject)有许多依赖关系。 我的问题是:如果我必须在需要测试的方法中使用我的模拟
我是一名优秀的程序员,十分优秀!