返回值在 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();
    });
});

似乎有一些不同步的问题。尝试使用 fakeAsyncasync,但没有解决。它总是采用主要的 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 方法上执行此操作。