Hello I'm testing a component and in that component I have CartService with two subjects. Im creating a spyObject for that service. And now when angular tries to subscribe to those subjects they are well undefined. Tried to returnValue of a Subject or something but nothing works for now. Still undefined.
This is the service and the Subjects.
export class CartService {
totalQuantity: Subject<number> = new Subject<number>();
totalPrice: Subject<number> = new Subject<number>();
}
Then in the component on ngOnInit() I just subscribe to them. This is the place Angular tries to subscribe but they are undefined and I don't know how to mock them
this.subscribePrice = this.cartService.totalPrice.subscribe(data => this.totalPrice = data);
this.subscribeQuantity = this.cartService.totalQuantity.subscribe(data => this.totalQuantity = data);
Here is the test class:
fdescribe('CheckoutComponent', () => {
let component: CheckoutComponent;
let fixture: ComponentFixture<CheckoutComponent>;
let el: DebugElement;
let messageToastrService: any;
let cartService: any;
let priceSubject: Subject<number>;
let quantitySubject: Subject<number>;
beforeEach(async(() => {
priceSubject = new Subject<number>();
quantitySubject = new Subject<number>();
const messageToastrSpy = jasmine.createSpyObj('MessageToastrService', ['success']);
const cartServiceSpy = jasmine.createSpyObj('CartService',
['getCartFromStorage', 'computeTotals'], ['totalQuantity', 'totalPrice']);
TestBed.configureTestingModule({
declarations: [ CheckoutComponent ],
imports: [
ProductsModule,
RouterTestingModule.withRoutes([]),
HttpClientTestingModule,
],
providers: [
{provide: MessageToastrService, useValue: messageToastrSpy},
{provide: CartService, useValue: cartServiceSpy},
]
})
.compileComponents()
.then(() => {
fixture = TestBed.createComponent(CheckoutComponent);
component = fixture.componentInstance;
el = fixture.debugElement;
messageToastrService = TestBed.inject(MessageToastrService);
cartService = TestBed.inject(CartService);
fixture.detectChanges();
});
}));
Now just concentrating on the matter at hand. These are the ways I tried to fix the thing. But still, nothing works.
it('should properly initialize component', function() {
component.ngOnInit();
// cartService.totalPrice.and.returnValue(priceSubject.asObservable());
// cartService.totalQuantity.and.returnValue(quantitySubject.asObservable());
cartService.totalPrice.and.returnValue(of());
cartService.totalQuantity.and.returnValue(of());
// (cartService.totalPrice as jasmine.Spy).and.returnValue(priceSubject.asObservable());
// (cartService.totalQuantity as jasmine.Spy).and.returnValue(quantitySubject.asObservable());
});
The trace:
Failed: Uncaught (in promise): TypeError: Cannot read property 'subscribe' of undefined
TypeError: Cannot read property 'subscribe' of undefined
at CheckoutComponent.uploadCartInfo (http://localhost:9876/_karma_webpack_/webpack:/src/app/modules/products/components/checkout/checkout.component.ts:62:55)
at CheckoutComponent.ngOnInit
error properties: Object({ rejection: TypeError: Cannot read property 'subscribe' of undefined, promise: [object Promise], zone: Zone({ _parent: Zone({ _parent: null, _name: '<root>', _properties: Object({ }), _zoneDelegate: ZoneDelegate({ _taskCounts: Object({ microTask: 0, macroTask: 0, eventTask: 0 }), zone: <circular reference: Object>, _parentDelegate: null, _forkZS: null, _forkDlgt: null, _forkCurrZone: null, _interceptZS: null, _interceptDlgt: null, _interceptCurrZone: null, _invokeZS: null, _invokeDlgt: null, _invokeCurrZone: null, _handleErrorZS: null, _handleErrorDlgt: null, _handleErrorCurrZone: null, _scheduleTaskZS: null, _scheduleTaskDlgt: null, _scheduleTaskCurrZone: null, _invokeTaskZS: null, _invokeTaskDlgt: null, _invokeTaskCurrZone: null, _cancelTaskZS: null, _cancelTaskDlgt: null, _cancelTaskCurrZone: null, _hasTaskZS: null, _hasTaskDlgt: null, _hasTaskDlgtOwner: null, _hasTaskCurrZone: null }) }), _name: 'ProxyZone', _properties: Object({ ProxyZoneSpec: ProxyZoneSpec({ defaultS ...
Error: Uncaught (in promise): TypeError: Cannot read property 'subscribe' of undefined
TypeError: Cannot read property 'subscribe' of undefined
at CheckoutComponent.uploadCartInfo (http://localhost:9876/_karma_webpack_/webpack:/src/app/modules/products/components/checkout/checkout.component.ts:62:55)
at CheckoutComponent.ngOnInit (http://localhost:9876/_karma_webpack_/webpack:/src/app/modules/products/components/checkout/checkout.component.ts:40:10)
at callHook (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:2922:1)
at callHooks (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:2892:1)
at executeInitAndCheckHooks (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:2844:1)
at refreshView (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:7213:1)
at renderComponentOrTemplate (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:7312:1)
at tickRootContext (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:8507:1)
at detectChangesInRootView (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:8532:1)
at RootViewRef.detectChanges (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:9918:1)
at resolvePromise (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone-evergreen.js:798:1)
at http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone-evergreen.js:864:1
at ZoneDelegate.invokeTask (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone-evergreen.js:399:1)
at AsyncTestZoneSpec.onInvokeTask (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone-testing.js:1016:1)
at ProxyZoneSpec.onInvokeTask (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone-testing.js:320:1)
at ZoneDelegate.invokeTask (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone-evergreen.js:398:1)
at Zone.runTask (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone-evergreen.js:167:1)
at drainMicroTaskQueue (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone-evergreen.js:569:1)
How can I fix this? Thanks.
Found the answer with help from Szymon.
First i had to change the spyObject of cartServiceSpy and underneath add those two fields to spy them.
const cartServiceSpy = jasmine.createSpyObj('CartService', ['getCartFromStorage', 'computeTotals']);
cartServiceSpy.totalQuantity = quantitySubject;
cartServiceSpy.totalPrice = priceSubject;