返回值在 spyOn 模拟服务茉莉花测试中没有改变
returnValue not changing on spyOn mock service jasmine test
我正在尝试测试一个使用服务的组件,该服务有一个 return 是布尔值的函数。基于此布尔值,我的组件可以更改其模板。
出于某种原因,return每个测试中的值并未覆盖我需要的 return值,因此模板可以实际更改和测试。
这是我的测试:
describe("LikeButtonComponent", () => {
let component: LikeButtonComponent;
let fixture: ComponentFixture<LikeButtonComponent>;
const mockService = jasmine.createSpyObj("UserService", {
isLiked$: of(true),
getPostId$: of("12983"),
likePost: () => {},
unlikePost: () => {}
});
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [LikeButtonComponent]
})
.overrideComponent(LikeButtonComponent, {
set: { providers: [{ provide: UserService, useValue: mockService }] }
})
.compileComponents()
.then(() => {
fixture = TestBed.createComponent(LikeButtonComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
}));
it("should render component", () => {
expect(component).toBeTruthy();
});
it("should call like", () => {
component.likePost();
expect(mockService.likePost).toHaveBeenCalledTimes(1);
});
it("should call unlike", () => {
component.unlikePost();
expect(mockService.unlikePost).toHaveBeenCalledTimes(1);
});
it("should have 'liked' class when isLiked is true", () => {
mockService.isLiked$.and.returnValue(of(true));
fixture.detectChanges();
const container = fixture.debugElement.nativeElement.querySelector(".likedButton");
expect(container.classList.contains("likedButton--active")).toBeTruthy();
});
it("should have 'unliked' class when isLiked is false", () => {
mockService.isLiked$.and.returnValue(of(false)); // <-- this isn't working as expected.
fixture.detectChanges();
const container = fixture.debugElement.nativeElement.querySelector(".unlikedButton");
expect(container.classList.contains("unlikedButton--active")).toBeTruthy();
});
});
似乎有一些不同步的问题。尝试使用 fakeAsync
或 async
,但没有解决。它总是采用主要的 spyCreate 值,所以如果我把它设置为 return Observable.of(false),它将保留在那里,无论我以后想如何在各个测试用例中更改它,它将无法工作或组件无法正确更新,因此我可以检查应用的 类。
我错过了什么?
谢谢。
问题是我们在此处将 isLiked$
硬编码为 true:
const mockService = jasmine.createSpyObj("UserService", {
isLiked$: of(true),
getPostId$: of("12983"),
likePost: () => {},
unlikePost: () => {}
});
为了解决这个问题,我会使用 BehaviorSubject。
import { BehaviorSubject } from 'rxjs';
....
describe("LikeButtonComponent", () => {
let component: LikeButtonComponent;
let fixture: ComponentFixture<LikeButtonComponent>;
// add this line
const isLikedBehaviorSubject$ = new BehaviorSubject(true);
const mockService = jasmine.createSpyObj("UserService", {
// link isLiked$ to that BehaviorSubject
isLiked$: isLikedBehaviorSubject$.asObservable(),
getPostId$: of("12983"),
likePost: () => {},
unlikePost: () => {}
});
....
it("should have 'unliked' class when isLiked is false", () => {
// change the BehaviorSubject to false
isLikedBehaviorSubject$.next(false);
fixture.detectChanges();
const container = fixture.debugElement.nativeElement.querySelector(".unlikedButton");
expect(container.classList.contains("unlikedButton--active")).toBeTruthy();
});
使用 BehaviorSubject 我们可以动态改变 isLiked$
的值。之前总是 of(true)
。我认为您不能对实例变量执行 mockService.isLiked$.and.returnValue(of(false));
(我假设这是一个实例变量)。您只能在 public 方法上执行此操作。
我正在尝试测试一个使用服务的组件,该服务有一个 return 是布尔值的函数。基于此布尔值,我的组件可以更改其模板。
出于某种原因,return每个测试中的值并未覆盖我需要的 return值,因此模板可以实际更改和测试。
这是我的测试:
describe("LikeButtonComponent", () => {
let component: LikeButtonComponent;
let fixture: ComponentFixture<LikeButtonComponent>;
const mockService = jasmine.createSpyObj("UserService", {
isLiked$: of(true),
getPostId$: of("12983"),
likePost: () => {},
unlikePost: () => {}
});
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [LikeButtonComponent]
})
.overrideComponent(LikeButtonComponent, {
set: { providers: [{ provide: UserService, useValue: mockService }] }
})
.compileComponents()
.then(() => {
fixture = TestBed.createComponent(LikeButtonComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
}));
it("should render component", () => {
expect(component).toBeTruthy();
});
it("should call like", () => {
component.likePost();
expect(mockService.likePost).toHaveBeenCalledTimes(1);
});
it("should call unlike", () => {
component.unlikePost();
expect(mockService.unlikePost).toHaveBeenCalledTimes(1);
});
it("should have 'liked' class when isLiked is true", () => {
mockService.isLiked$.and.returnValue(of(true));
fixture.detectChanges();
const container = fixture.debugElement.nativeElement.querySelector(".likedButton");
expect(container.classList.contains("likedButton--active")).toBeTruthy();
});
it("should have 'unliked' class when isLiked is false", () => {
mockService.isLiked$.and.returnValue(of(false)); // <-- this isn't working as expected.
fixture.detectChanges();
const container = fixture.debugElement.nativeElement.querySelector(".unlikedButton");
expect(container.classList.contains("unlikedButton--active")).toBeTruthy();
});
});
似乎有一些不同步的问题。尝试使用 fakeAsync
或 async
,但没有解决。它总是采用主要的 spyCreate 值,所以如果我把它设置为 return Observable.of(false),它将保留在那里,无论我以后想如何在各个测试用例中更改它,它将无法工作或组件无法正确更新,因此我可以检查应用的 类。
我错过了什么?
谢谢。
问题是我们在此处将 isLiked$
硬编码为 true:
const mockService = jasmine.createSpyObj("UserService", {
isLiked$: of(true),
getPostId$: of("12983"),
likePost: () => {},
unlikePost: () => {}
});
为了解决这个问题,我会使用 BehaviorSubject。
import { BehaviorSubject } from 'rxjs';
....
describe("LikeButtonComponent", () => {
let component: LikeButtonComponent;
let fixture: ComponentFixture<LikeButtonComponent>;
// add this line
const isLikedBehaviorSubject$ = new BehaviorSubject(true);
const mockService = jasmine.createSpyObj("UserService", {
// link isLiked$ to that BehaviorSubject
isLiked$: isLikedBehaviorSubject$.asObservable(),
getPostId$: of("12983"),
likePost: () => {},
unlikePost: () => {}
});
....
it("should have 'unliked' class when isLiked is false", () => {
// change the BehaviorSubject to false
isLikedBehaviorSubject$.next(false);
fixture.detectChanges();
const container = fixture.debugElement.nativeElement.querySelector(".unlikedButton");
expect(container.classList.contains("unlikedButton--active")).toBeTruthy();
});
使用 BehaviorSubject 我们可以动态改变 isLiked$
的值。之前总是 of(true)
。我认为您不能对实例变量执行 mockService.isLiked$.and.returnValue(of(false));
(我假设这是一个实例变量)。您只能在 public 方法上执行此操作。