1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.
  2. Anuncie Aqui
    Anuncie aqui você Também: fdantas@4each.com.br

How to properly mock NGXS Select in a component using the Store

Discussão em 'Angular' iniciado por gizmo, Junho 12, 2025.

  1. gizmo

    gizmo Guest

    I have a component that fetches some information from a NGXS Store, that I need to create unit tests for. The component looks like this:

    @Component({
    standalone: true,
    selector: 'app-task-selection-menu',
    templateUrl: './task-selection-menu.component.html',
    styleUrl: './task-selection-menu.component.scss',
    changeDetection: ChangeDetectionStrategy.OnPush,
    imports: [TextComponent, CheckboxComponent, TooltipModule],
    })
    export class TaskSelectionMenuComponent implements OnInit, OnDestroy {
    private readonly store = inject(Store);
    private readonly configManager = inject(ConfigurationManagerService);
    private readonly cdr = inject(ChangeDetectorRef);
    private readonly destroy$ = new Subject<void>();
    readonly Icons = Icons;
    id: string | undefined;
    tasks = select(TaskSelectionSelectors.props.tasks);
    state = select(TaskSelectionSelectors.props.state);

    ngOnInit(): void {
    this.getDailyDetails();
    }
    ngOnDestroy(): void {
    this.destroy$.next();
    }

    async getDailyDetails() {
    const dailyTasks = await this.configManager.getTasks('daily');
    if (dailyTasks) {
    this.id = dailyTasks.id;

    this.store.dispatch(new TaskSelectionActions.FetchAll(this.id));
    }
    }

    isTaskSelected(task: Task): boolean {
    return task.selectionState === TaskSelectionState.Selected;
    }

    updateTask(task: Task, $event: boolean) {
    if (this.id) {
    const newState = {
    selectionState: $event ? TaskSelectionState.Selected : TaskSelectionState.Unselected,
    };
    this.store.dispatch(
    new TaskSelectionActions.UpdateTask(this.id, task.id, newState),
    );
    }
    this.cdr.markForCheck();
    }

    // some methods for displaying the list of checkboxes in the template correctly

    }



    I've tried a few different setups for the testing, but I keep getting Errors like this:

    // if i mock out select/selectSignal/dispatch and create the Store as a Jasmine SpyObj
    FAILED: should create
    NullInjectorError: R3InjectorError(Standalone[TaskSelectionMenuComponent])[Logger -> Logger -> LogTarget -> LogTarget]:
    NullInjectorError: No provider for LogTarget!
    error properties: Object({ ngTempTokenPath: null, ngTokenPath: [ 'Logger', 'Logger', 'LogTarget', 'LogTarget' ] })
    at NullInjector.get (node_modules/@angular/core/fesm2022/core.mjs:1630:27)
    at R3Injector.call (node_modules/@angular/core/fesm2022/core.mjs:2159:33)
    at R3Injector.apply (node_modules/ng-mocks/index.mjs:1:129465)
    at R3Injector.get (node_modules/ng-mocks/index.mjs:1:6416)
    at R3Injector.call (node_modules/@angular/core/fesm2022/core.mjs:2159:33)
    at R3Injector.apply (node_modules/ng-mocks/index.mjs:1:129465)
    at R3Injector.get (node_modules/ng-mocks/index.mjs:1:6416)
    at injectInjectorOnly (node_modules/@angular/core/fesm2022/core.mjs:1125:32)
    at ɵɵinject (node_modules/@angular/core/fesm2022/core.mjs:1131:60)
    at inject (node_modules/@angular/core/fesm2022/core.mjs:1217:12)


    // if i don't mock out select/selectSignal/dispatch and inject the Store into the storeSpy, I get this error:
    FAILED: should create
    NullInjectorError: R3InjectorError(DynamicTestModule)[Store -> InternalStateOperations -> InternalDispatcher -> InternalNgxsExecutionStrategy -> InjectionToken NGXS_EXECUTION_STRATEGY -> InjectionToken CUSTOM_NGXS_EXECUTION_STRATEGY -> InjectionToken CUSTOM_NGXS_EXECUTION_STRATEGY]:
    NullInjectorError: No provider for InjectionToken CUSTOM_NGXS_EXECUTION_STRATEGY!
    error properties: Object({ ngTempTokenPath: null, ngTokenPath: [ 'Store', 'InternalStateOperations', 'InternalDispatcher', 'InternalNgxsExecutionStrategy', 'InjectionToken NGXS_EXECUTION_STRATEGY', 'InjectionToken CUSTOM_NGXS_EXECUTION_STRATEGY', 'InjectionToken CUSTOM_NGXS_EXECUTION_STRATEGY' ] })
    at NullInjector.get (node_modules/@angular/core/fesm2022/core.mjs:1630:27)
    at R3Injector.call (node_modules/@angular/core/fesm2022/core.mjs:2159:33)
    at R3Injector.apply (node_modules/ng-mocks/index.mjs:1:129465)
    at R3Injector.get (node_modules/ng-mocks/index.mjs:1:6416)
    at R3Injector.call (node_modules/@angular/core/fesm2022/core.mjs:2159:33)
    at R3Injector.apply (node_modules/ng-mocks/index.mjs:1:129465)
    at R3Injector.get (node_modules/ng-mocks/index.mjs:1:6416)
    at Object.factory (node_modules/@ngxs/store/fesm2022/ngxs-store.mjs:138:44)
    at callback (node_modules/@angular/core/fesm2022/core.mjs:2282:47)
    at runInInjectorProfilerContext (node_modules/@angular/core/fesm2022/core.mjs:884:9)


    My test setup looks like this (commented out code -> previous tries):

    describe('TaskSelectionMenuComponent', () => {
    let component: TaskSelectionMenuComponent ;
    let fixture: ComponentFixture<TaskSelectionMenuComponent >;
    // let storeSpy: Store;
    let storeSpy: jasmine.SpyObj<Store>;
    let configManagerServiceMock: jasmine.SpyObj<ConfigurationManagerService>;

    const mockSessionId = 'test-session-id';
    const mockResponseSession: ResponseSession[] = [
    // default values
    ];
    const defaults: TaskSelectionStateModel = {
    isLoading: false,
    id: undefined,
    state: TaskState.Default,
    tasks: [],
    error: undefined,
    };

    beforeEach(() => {
    // storeSpy = TestBed.inject(Store);
    // storeSpy.reset(defaults);
    storeSpy = jasmine.createSpyObj('Store', ['select', 'dispatch', 'selectSignal']);

    // storeSpy.select.and.returnValue(of(defaults));
    // storeSpy.dispatch.and.resolveTo(undefined);
    // storeSpy.selectSignal.and.resolveTo(undefined);

    // storeSpy.select.and.returnValue(jasmine.createSpyObj('Signal', ['pipe']));
    // storeSpy.dispatch.and.returnValue(jasmine.createSpyObj('Observable', ['subscribe']));
    // storeSpy.selectSignal.and.returnValue(jasmine.createSpyObj('Signal', ['subscribe']));

    configManagerServiceMock = jasmine.createSpyObj('ConfigurationManagerService', ['getSessions']);
    configManagerServiceMock.getSessions.and.resolveTo(mockResponseSession);

    TestBed.configureTestingModule({
    imports: [TaskSelectionMenuComponent],
    providers: [
    { provide: Store, useValue: storeSpy },
    { provide: ConfigurationManagerService, useValue: configManagerServiceMock },
    ],
    }).compileComponents();
    TestBed.inject(Store);
    TestBed.inject(ConfigurationManagerService);

    fixture = TestBed.createComponent(TaskSelectionMenuComponent);
    component = fixture.componentInstance;
    });

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



    Versions: Angular 19.2.0 NGXS Store 19.0.0

    Where am I going wrong? I've checked in the documentation and SO, but I've only found questions about how to unit test the Store itself, not components that use the store. If I've missed something in the docs or somewhere else, please let me know!

    Thank you!

    Continue reading...

Compartilhe esta Página