Why does expect(component['numberHogeNames']()).toBe(3)
fail in my Angular test?
Here is a simplified version of my code:
// hoge-service.ts
interface HogeData {
id: string;
name: string;
}
export class HogeService {
private dataSrc = signal<HogeData[]>([
{ id: '1', name: 'kage' },
{ id: '2', name: 'sage' },
{ id: '3', name: 'tage' },
{ id: '4', name: 'nage' },
{ id: '5', name: 'mage' },
{ id: '6', name: 'yage' },
...
]);
numberHogeNames = computed<number>(() => {
return this.dataSrc().filter((item) => item.name === 'hoge').length;
});
}
// hoge-component.ts
@Component({
standalone: true,
providers: [HogeService],
template: `<div class="num">{{ numberHogeNames() }}</div>`,
encapsulation: ViewEncapsulation.Emulated,
changeDetection: ChangeDetectionStrategy.OnPush,
...
})
export class HogeComponent {
private hogeService = inject(HogeService);
protected numberHogeNames = computed<number>(() => {
return this.hogeService.numberHogeNames();
});
}
// hoge-component.spec.ts
describe('Hoge Test', () => {
let component: HogeComponent;
let fixture: ComponentFixture<HogeComponent>;
let hogeService: HogeService;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [HogeComponent],
providers: [HogeService],
}).compileComponents();
fixture = TestBed.createComponent(HogeComponent);
component = fixture.componentInstance;
hogeService = TestBed.inject(HogeService);
});
it('Case 01', async () => {
hogeService['dataSrc'].update((current) => {
current.forEach((item, index) => {
if (index < 3) item.name = 'hoge';
});
return [...current];
});
// Success
expect(hogeService.numberHogeNames()).toBe(3);
fixture.detectChanges();
// Failed (Expected 0 to be 3.)
expect(component['numberHogeNames']()).toBe(3);
})
});
Despite the test failure, the component works correctly when used in the actual application. The value of numberHogeNames
on the screen updates as expected when dataSrc
changes.
I tried modifying the private dataSrc
signal in the HogeService
by using update()
to change some items' name
properties to hoge
. After updating dataSrc
, I expected both hogeService.numberHogeNames()
and component['numberHogeNames']()
to return 3
since there are three items with the name hoge
.
In the test, hogeService.numberHogeNames()
updates correctly to 3
, which is the expected behavior. However, component['numberHogeNames']()
still returns the old value and does not update as expected.
I have tried using fixture.detectChanges()
and waiting for a short delay using setTimeout
to see if the component’s computed signal would update, but these attempts did not resolve the issue.
I expect the component’s computed signal (numberHogeNames
) to reflect the changes in the service's signal (dataSrc
) just as it does in the actual application where everything works as intended.
You need to reference the service that is injected into the component (i.e. component.hogeService)
:
component.hogeService['dataSrc'].update((current) => {
current.forEach((item, index) => {
if (index < 3) item.name = 'hoge';
});
return [...current];
});
Then later:
expect(component.hogeService.numberHogeNames()).toBe(3);
The test after these changes should pass.