Reputation: 429
First, I apologize. I'm really new to Angular and am not sure I know enough to ask a good question, let alone provide some small working examples.
I'm trying to use spyOn in a unit test, and not having much luck.
Basically, my unit test calls a method on component that calls a service1, that calls another service2.
When I try to spyOn on service1, it doesn't use the mock value that I provide. It calls the "real" ServiceProvidersHTTPService.getAllUsers and uses AppConfigService instead of MockAppConfigService.
I'll start by copying my Test.
describe('ProjectAnalystComponent', () => {
let component: ProjectAnalystComponent;
let fixture: ComponentFixture<ProjectAnalystComponent>;
let service: ServiceProvidersHTTPService ;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [HttpClientModule, RouterTestingModule],
declarations: [ ProjectAnalystComponent ],
providers:
[
ServiceProvidersHTTPService,
CurrentCreateProjectService,
NotificationService,
MessageService,
ProjectLeadAnalystHTTPService,
ExceptionService,
{provide: AppConfigService, useClass: MockAppConfigService }
],
schemas: [CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ProjectAnalystComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
console.log("######### Did this run");
let service = fixture.debugElement.injector.get(ServiceProvidersHTTPService);
spyOn(service, 'getAllUsers').and.returnValue('{}');
expect(component).toBeTruthy();
});
});
Upvotes: 2
Views: 22425
Reputation:
TL;DR Mock your service.
In your testbed, you provide the actual service :
providers:[ServiceProvidersHTTPService, ...
This means you actually call the real methods of your service.
If you mock your service, like you did there :
{provide: AppConfigService, useClass: MockAppConfigService }
Then you call random functions that you declare in your mock.
Another advantage of mocking, you get rid of the dependencies of your dependencies.
As you said, your service calls another service : if you mock your first service, you don't have to add the dependencies of this service into your testbed.
So, they way to go :
const mock = {
provide: ServiceProvidersHTTPService,
useValue: {
getAllUsers: () => null
}
};
In your testbed now :
providers: [mock, ...
In useValue
, you must put all the variables and all the functions of your actual service, and mock them.
In this case, instead of making HTTP calls, your function getAllUsers
will simply return null. You can make it return anything you want (the good practice is to return a value that is the same type of the value that should be returned).
Last piece of advice : your unit tests should test only the functions and methods of your actual feature (here being ProjectAnalystComponent
). You should not test if your service call the other service here : you should test that in the unit testing of your service.
If you have any questions, feel free to ask !
Upvotes: 4