Angular 17+ testing services with signals and effects

Discussão em 'Angular' iniciado por Nenad, Março 18, 2025.

  1. Nenad

    Nenad Guest

    I have a service A which exposes a public method that sets/updates a private signal in the service. Anytime the value of the signal in service A changes, it triggers an effect (called in the constructor of the service), that calls a private method of service A.

    The private method is used to call a number of other different services' methods, but for the sake of simplicity let's just say that it's only one service - service B, and a exposed method of service B.

    The code works as it's supposed to, but I need to write tests for this system and it seems like I cannot wrap my head around how services with signals, especially the triggered effects.

    The goal of the test is to verify that once public method of service A (which updates the signal) is called, that also the whole chain happens, i.e. eventually public method of service B is called.

    How can I get the test to work with Signals?

    Example:

    @Injectable({
    providedIn: 'root'
    })
    export class ServiceA {
    private signalA: Signal<number> = signal(0);

    constructor(private readonly serviceB: ServiceB) {
    effect(() => {
    const signalAValue = signalA();
    this.privateMethod(signalAValue);
    });
    }

    public publicMethodA(value: number): void {
    this.signalA.update(value);
    }

    private privateMethodA(arg: number): void {
    this.serviceB.publicMethodB(arg)
    }
    }


    Test for ServiceA:

    describe('ServiceA', () => {
    let serviceA: ServiceA;
    let serviceB: ServiceB;

    beforeEach(() => {
    TestBed.configureTestingModule({
    providers: [
    ServiceA,
    ServiceB
    ]
    });

    serviceA = TestBed.inject(ServiceA);
    serviceB = TestBed.inject(ServiceB);
    });

    it('should call publicMethodB of ServiceB when publicMethodA of ServiceA is called', fakeAsync(() => {
    jest.spyOn(serviceA, 'publicMethodA');
    service.publicMethod(1);

    expect(serviceB.publicMethodB).toHaveBeenCalled();
    }));
    });


    Test fails with:

    Expected number of calls: >= 1
    Received number of calls: 0

    Continue reading...

Compartilhe esta Página