首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何对服务的订阅进行单元测试?

如何对服务的订阅进行单元测试?
EN

Stack Overflow用户
提问于 2022-03-03 18:55:33
回答 1查看 1.9K关注 0票数 1

我一直试图找到一种方法来测试一个订阅,这个订阅是在一个被模仿的服务上使用Jest来测试的。但是,我找不到一种方法来模拟可观察到的isMobile属性并测试其赋值。

当我尝试spyOn,然后模拟该服务以返回一个值时,它永远不会更新。我希望能够测试来自服务的不同响应的代码。

下面的代码。

组件

代码语言:javascript
复制
import { Component, Input, OnInit } from '@angular/core';
import { BREAKPOINT, BreakpointService } from '../../services';
 
@Component({
  selector: 'auxiliary-bar',
  templateUrl: './auxiliary-bar.component.html',
  styleUrls: ['./auxiliary-bar.component.scss'],
})
export class AuxiliaryBarComponent implements OnInit { 
  public isMobile = false;
 
  constructor(private breakpointService: BreakpointService) {}
 
  ngOnInit(): void {
    this.breakpointService.onBreakpoint$.subscribe(
      (breakpoint) => (this.isMobile = breakpoint <= BREAKPOINT.SM),
    );
  }
}

断点服务

代码语言:javascript
复制
import { Injectable, NgZone, OnDestroy } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { distinctUntilChanged } from 'rxjs/operators';

export enum BREAKPOINT {
  XS,
  SM,
  MD,
  LG,
  XL,
}

@Injectable({
  providedIn: 'root',
})
export class BreakpointService implements OnDestroy {
  private breakpointSubject: Subject<BREAKPOINT> = new Subject();
  private observer!: ResizeObserver;
  private sizes = [
    {
      id: BREAKPOINT.SM,
      width: 0,
    },
    {
      id: BREAKPOINT.SM,
      width: 320,
    },
    {
      id: BREAKPOINT.MD,
      width: 768,
    },
    {
      id: BREAKPOINT.LG,
      width: 1024,
    },
    {
      id: BREAKPOINT.XL,
      width: 1200,
    },
  ];

  constructor(private zone: NgZone) {
    this.observer = new ResizeObserver((entries) => {
      this.zone.run(() => {
        const matchedSize = this.sizes
          .slice(1)
          .reverse()
          .find(
            (size) => window.matchMedia(`(min-width: ${size.width}px)`).matches,
          );
        this.breakpointSubject.next(
          matchedSize ? matchedSize.id : BREAKPOINT.XS,
        );
      });
    });
    this.observer.observe(document.body);
  }

  ngOnDestroy(): void {
    this.observer.unobserve(document.body);
  }

  public get onBreakpoint$(): Observable<BREAKPOINT> {
    return this.breakpointSubject.asObservable().pipe(distinctUntilChanged());
  }
}

试用期套房

代码语言:javascript
复制
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MockProvider } from 'ng-mocks';
import { Observable, of } from 'rxjs';

import { BreakpointService } from '../../services';
import { AuxiliaryBarComponent } from './auxiliary-bar.component';

describe('AuxiliaryBarComponent', () => {
  let component: AuxiliaryBarComponent;
  let fixture: ComponentFixture<AuxiliaryBarComponent>;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [
        AuxiliaryBarComponent,
      ],
      providers: [
        MockProvider(BreakpointService, {
          onBreakpoint$: new Observable(),
        }),
      ],
    }).compileComponents();
  });

  beforeEach(() => {
    fixture = TestBed.createComponent(AuxiliaryBarComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });

  it('should', () => {
    const breakpointService = TestBed.inject(BreakpointService);
    const spy = jest
      .spyOn(breakpointService, 'onBreakpoint$', 'get')
      .mockReturnValue(of(3));
    fixture.detectChanges();
    expect(breakpointService.onBreakpoint$.subscribe).toHaveBeenCalled();
  });
)};
EN

回答 1

Stack Overflow用户

发布于 2022-03-03 20:52:19

我很确定为时已晚,因为组件已经被实例化,因此ngInit在it启动时已经被调用了。如果我是对的,那么修复可能就像在上一个component.ngOnInit()之前插入fixture.detectChanges()来重新触发它一样容易。

另外,如果您可以帮助组件,则不应该订阅它。相反,如果它适合您的需要,那么我会将组件的ngOnInit更改为

代码语言:javascript
复制
public isMobile$: Observable<boolean>;
ngOnInit(): void {
  this.isMobile$ = this.breakpointService.onBreakpoint$.pipe(
    map(breakpoint => breakpoint <= BREAKPOINT.SM)
  );
}

然后,在模板中,无论您曾经拥有isMobile,还是使用(isMobile$ | async)

但是,如果您必须在服务或组件中订阅(或者为了安全和良好的编程实践也可以这样做),那么您的服务应该有一个调用ngOnDestroy的this.breakpointSubject?complete();

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71342382

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档