我已经尝试过此SO帖子,但这不是我的情况。
我有一个服务(AnimationService
),该服务取决于另一个服务(AnimationStateService
)。这个AnimationStateService
有一个吸气剂state
,我想在测试中模拟它。所以我的测试看起来像这样:
animation.service.spec.ts
describe("AnimationService", () => {
let animationService: SpyObj<AnimationService>;
let animationStateService: SpyObj<AnimationStateService>;
beforeEach(() => {
const spyAnimationStateService = createSpyObj("AnimationStateService", ["changeStatus"]);
TestBed.configureTestingModule({
providers: [
AnimationService,
{provide: AnimationStateService, useValue: spyAnimationStateService}
]
});
animationStateService = TestBed.get(AnimationStateService);
animationService = TestBed.get(AnimationService);
});
fit("should call changeStatus if status is AnimationStatus.Stopped", () => {
// Arrange
// animationStateService.status.and.returnValue(AnimationStatus.Stopped); - Doesn't work
// spyOnProperty(animationStateService, "status").and.returnValue(AnimationStatus.Stopped); - Doesn't work
// animationStateService.status = AnimationStatus.Stopped; - Works, but with TSLint error
// Act
animationService.start();
// Assert
expect(animationStateService.changeStatus).toHaveBeenCalled();
});
});
animation-state.service.spec.ts
@Injectable()
export class AnimationStateService {
public get status(): AnimationStatus { return this.state.animation.status; }
...
}
当我尝试用以下方法模拟吸气剂时:
animationStateService.status.and.returnValue(AnimationStatus.Stopped);
或:
spyOnProperty(animationStateService, "status").and.returnValue(AnimationStatus.Stopped);
它不起作用。吸气剂根本没有返回我已经设置的值。
此方法有效:
animationStateService.status = AnimationStatus.Stopped;
但是它给了我一个TSLint错误:
Cannot assign to 'status' because it is a constant or a read-only property.
所以到现在为止我还不知道,还有什么我应该尝试正确地模拟吸气剂且没有错误。
答案 0 :(得分:1)
您应该使用带有第三个 accessType
参数的 spyOnProperty(obj, propertyName, accessTypeopt) → {Spy} 将间谍安装到 getter
方法上。
例如
animation.service.ts
:
import { Injectable } from '@angular/core';
import { AnimationStateService } from './animation-state.service';
@Injectable()
export class AnimationService {
constructor(private animationStateService: AnimationStateService) {}
start() {
return this.animationStateService.status;
}
}
animation-state.service.ts
:
import { Injectable } from '@angular/core';
export enum AnimationStatus {
Stopped = 'Stopped',
Started = 'Started',
}
@Injectable()
export class AnimationStateService {
state = {
animation: {
status: AnimationStatus.Started,
},
};
public get status(): AnimationStatus {
return this.state.animation.status;
}
}
animation.service.spec.ts
:
import { TestBed } from '@angular/core/testing';
import {
AnimationStateService,
AnimationStatus,
} from './animation-state.service';
import { AnimationService } from './animation.service';
fdescribe('53333050', () => {
let animationStateService: AnimationStateService;
let animationService: AnimationService;
beforeEach(() => {
TestBed.configureTestingModule({
providers: [AnimationService, AnimationStateService],
});
animationStateService = TestBed.get(AnimationStateService);
animationService = TestBed.get(AnimationService);
});
it('should call changeStatus if status is AnimationStatus.Stopped', () => {
// Arrange
const statusGetterSpy = spyOnProperty(
animationStateService,
'status',
'get'
).and.returnValue(AnimationStatus.Stopped);
// Act
const actual = animationService.start();
expect(actual).toEqual(AnimationStatus.Stopped);
// Assert
expect(statusGetterSpy).toHaveBeenCalled();
});
});
单元测试结果: