angular Jasmine - cannot set property of undefined
Solution 1
I'm not sure why you're using provide
and useClass
to provide this service here. That's generally done when you have to create a custom/lightweight implementation of a service on your own(For instance, when you have things like Angular's Router
and ActivatedRoute
injected as a dependency on you controller).
For the current scenario though, you just need a reference to the injected dependency for a service that you have created.
So you can simply use the providers
array to provide it to your testing module, like this:
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ModalComponent ],
providers: [ GridService ]
})
.compileComponents();
}));
And then you can get a reference to the GridService
by using fixture.debugElement.injector.get(GridService);
and test your save
method like this:
describe('save', () => {
it('should set gridCellUpdated on GridService to false', () => {
let gridService = fixture.debugElement.injector.get(GridService);
expect(gridService.gridCellUpdated).toBeTruthy();
component.save();
expect(gridService.gridCellUpdated).toBeFalsy();
});
});
Update
If you still have to use the provide
way of providing your service, use useClass
instead of use
. Something like this:
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ModalComponent ],
providers: [ { provide: GridService, useClass: GridServiceMock } ]
})
.compileComponents();
}));
And to write the test the same way as told. It should work.
UPDATE Here's the whole test file, just for your reference:
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { GridService } from './../../services/grid.service';
import { ModalComponent } from './modal.component';
class GridServiceMock {
public gridCellUpdated = false;
}
describe('ModalComponent', () => {
let component: ModalComponent;
let fixture: ComponentFixture<ModalComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ModalComponent ],
providers: [ { provide: GridService, useClass: GridServiceMock } ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ModalComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should be created', () => {
expect(component).toBeTruthy();
});
describe('save', () => {
it('should set gridCellUpdated on GridService to false', () => {
let gridService = fixture.debugElement.injector.get(GridService);
expect(gridService.gridCellUpdated).toBeTruthy();
component.save();
expect(gridService.gridCellUpdated).toBeFalsy();
});
});
});
And the tests are passing:
Hope that helps!
Solution 2
as @Vega mentioned in his comment: the service is not a property of the component. It will be injected.
Your setup of the Testing Module is correct and you can get the service from the Testbed like this:
let gridService: GridService;
let fixture: ComponentFixture<ModalComponent>;
let component: ModalComponent;
TestBed.configureTestingModule({...});
TestBed.compileComponents().then(() => {
fixture = TestBed.createComponent( ModalComponent );
component = fixture.debugElement.componentInstance;
gridService= fixture.debugElement.injector.get( GridService );
} );
It will get an instance of the GridService as GridServiceMock. Your test should success now.
Regards
Ish
Updated on June 14, 2022Comments
-
Ish almost 2 years
My component code:
public save() { this.gridService.gridCellUpdated = false; }
My Jasmine code
class GridServiceMock { public gridCellUpdated = false; } let gridService: GridService; beforeEach( async(() => { TestBed.configureTestingModule({ declarations: [ModalComponent, BsModalDirective], providers: [{ provide: GridService, use: GridServiceMock }] }) .compileComponents(); }); ); it('should save assets', () => { gridService = fixture.debugElement.injector.get(GridService); component.save(); expect(gridService.gridCellUpdated).toBeFalsy(); });
My error:
TypeError: Cannot set property 'gridCellUpdated' of undefined
Edit: Updated the code by following below solutions but still get the same error.
-
Ish over 6 yearsWhat is the reason for the downvote ?
-
Mihailo over 6 yearsI'm not sure but I disagree with them so I'll null it out...
-
Mihailo over 6 yearsHave you tried injecting it into your test?
inject([GridService], (gridService: GridService)
? -
Vega over 6 yearsI think it's related to the fact that gridService is not component property.
-
-
Ish over 6 yearsDid the same way like you said. but the I am getting the same error.
-
Ish over 6 yearsfollowed this way too but the error remains the same.
-
SiddAjmera over 6 yearsIn your question you're referring to your service via your controller(
component.gridService.gridCellUpdated
). Did you update that? You should check again. Probably something's still missing. -
Ish over 6 yearsPlease check my new code. I updated by following the solutions.
-
SiddAjmera over 6 yearsYou're still using the
providers: [{ provide: GridService, use: GridServiceMock }]
to provide your service. I've specified not to do that. -
Ish over 6 yearsIsn't there any way where I could use the mocked service? that's what I am been asked to do
-
SiddAjmera over 6 yearsYou should be asking them as to why they're telling you to do it this way. I've updated my answer anyway. It should work with the latest updated answer that I provided.
-
SiddAjmera over 6 yearsLet us continue this discussion in chat.