简体   繁体   中英

SpyOn in Angular testing

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();
  });
});

TL;DR Mock your service.

Explanation

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 !

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM