I would like to unit test an Angular 10 component. In the component's ngOnInit method, this code appears:
this.subscriptions.push(
this.myService.getDataSubject.subscribe((results) => {
this.data = results;
}
);
Also, in the unit test
beforeEach(async(() => {
TestBed.configureTestingModule({
providers: [MyService]
}).compileComponents();
})
My unit test includes
beforeEach(() => {
spyOnProperty(myService, 'getDataSubject', 'get').and.returnValue(of(mockData));
}
In the service itself
private dataSubject: BehaviorSubject<any> = new BehaviorSubject({});
getDataSubject = this.dataSubject.asObservable();
The unit test fails. I've tried multiple variations but cannot get the mockData value to be returned. When writing a unit test for a component that subscribes to a property tied to a BehaviorSubject, what am I supposed to do?
It's a bit confusing topic, but there are two options (and it's definately not using .and.callFake(()=>of(MockData))
):
To return some mock data from service property, it's better to use SpyObject (to avoid providers mess from your service). Or you can create a fully mocked service with duplicated methods and properties.
In your case, while using SpyObject, to get mocked value you can try this:
describe('Using observable property', () => {
let service: ServiceClassName;
beforeEach(async () => {
const serviceSpy = jasmine.createSpyObj('ServiceClassName', [
// properties and methods list
'observable$'
]);
await TestBed.configureTestingModule({
providers: [
{provide: ServiceClassName, userValue: serviceSpy}
]
}).compileComponents();
});
beforeEach(() => {
service = TestBed.inject(ServiceClassName);
// actual defining mock data
service.observable$ = of({}); // empty object as mock data
});
it('test case', () => {
service.observable$.subscribe(value => {
console.log(value); // {}
});
});
});
In fact, you don't need to subscribe to observable property, it's just for example. Also, in case your component subscribed from service observable$
it would also get this mocked value