如何在 Angular 中对 NGXS 进行单元测试?

How to unit test NGXS in Angular?

我正在尝试为 ngOnIt 中的简单 NGXS 调度事件编写单元测试。我也尝试按照 NGXS 文档进行操作,但没有用。有人可以指导我吗?

charts.component.ts:

import { BarchartState } from './states/barchart-state/barchart.state';
import * as BarchartActions from './states/barchart-state/barchart.actions';

@Component({
selector: 'charts',
templateUrl: './charts.component.html',
styleUrls: ['./charts.component.scss'],
})

export class ChartsComponent implements OnInit {
@Select(BarchartState.simpleChartData) barchartData$: Observable<any>;
@Select(BarchartState.isLoading) barchartIsLoading$: Observable<boolean>;

constructor(private store: Store) { }

ngOnInit(): void {
  this.store.dispatch([
  new BarchartActions.Fetch(),
  ]);
 }
}

charts.component.spec.ts

import { ComponentFixture, TestBed } from '@angular/core/testing';
import { NgxsModule, Store } from '@ngxs/store';
import { ChartsComponent } from './charts.component';
import { BarchartService } from './states/barchart-state/barchart.service';
import { BarchartState } from './states/barchart-state/barchart.state';
import * as BarchartActions from './states/barchart-state/barchart.actions';


describe('ChartsComponent ', () => {
  let component: ChartsComponent ;
  let fixture: ComponentFixture<ChartsComponent >;
  let store: Store;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [ ChartsComponent ],
      imports: [
        NgxsModule.forRoot([BarchartState])
      ],
      providers: [
        BarchartService
      ]
    })
    .compileComponents();
  });

  beforeEach(() => {
    fixture = TestBed.createComponent(ChartsComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
    store = TestBed.inject(Store);
  });

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

  // I tried doing this but it doesn't work. It gives an error that simpleChartData is undefined
  // Can someone please guide what should I write in the test below?
  it('it should dispatch barchart fetch action', () => {
    store.dispatch(new BarchartActions.Fetch());

    const data = store.selectSnapshot(state => state.barchart.simpleChartData);
    expect(data).toBe(true);
  });

});

barchart.actions.ts

export class Fetch {
 static readonly type = '[Barchart] Fetch';
}

任何线索都会有所帮助!谢谢!

我会这样做:

我写了很多评论,所以你可以通过它来理解。

describe('ChartsComponent ', () => {
  // add dispatchSpy variable so we will know when it is called
  let dispatchSpy: jasmine.Spy;
  let component: ChartsComponent ;
  let fixture: ComponentFixture<ChartsComponent >;
  let store: Store;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [ ChartsComponent ],
      imports: [
        NgxsModule.forRoot([BarchartState])
      ],
      providers: [
        BarchartService
      ]
    })
    .compileComponents();
  });

  beforeEach(() => {
    fixture = TestBed.createComponent(ChartsComponent);
    component = fixture.componentInstance;
    // get a handle on the store before so we can see when dispatch was called
    store = TestBed.inject(Store);
    // assign dispatchSpy to when store.dispatch is called
    // and put callThrough so when it is actually called, call the actual
    // implementation so the store gets notified
    dispatchSpy = spyOn(store, 'dispatch').and.callThrough();
    // the first fixture.detectChanges() we call is when
    // ngOnInit is called. That's why we had to get a handle on the store
    // before the first fixture.detectChanges()
    fixture.detectChanges();
    
  });

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

  // I tried doing this but it doesn't work. It gives an error that simpleChartData is undefined
  // Can someone please guide what should I write in the test below?
  it('it should dispatch barchart fetch action', () => {
    // it should be as simple as this
    // The first fixture.detectChanges calls ngOnInit for us and we have a
    // handle on when store.dispatch is called before ngOnInit
    expect(dispatchSpy).toHaveBeenCalledWith([new BarchartActions.Fetch(),]);
  });

});