Tom Rudge
Tom Rudge

Reputation: 3272

UseValue of a MockService in Jasmine unit test causes test fail

I've created a StackBlitz with the karma/jasmine loader running so you can see the test pass/fail.

The application is working as it should.

My tests should be ok and will pass, however I'm getting a strange error with using a mockservice instead of the proper service to createspyobject on.

component.ts

  getReportFunc(): void {
    this.reportService.getReport(this.urn).subscribe(selectedReport => {
      this.model = selectedReport;
    });
  }

Simple call to a service to fetch "getReport". I will add a test to check that the report has been called. however cant because of this issue.

spec.ts

describe("SearchComponent", () => {
  let component: SearchComponent;
  let fixture: ComponentFixture<SearchComponent>;
  let mockReportService;

  beforeEach(async(() => {
      mockReportService = jasmine.createSpyObj(['getReport']);
    TestBed.configureTestingModule({
      declarations: [SearchComponent],
      providers: [
        //ReportService,
            { provide: ReportService, useValue: mockReportService },
...

The issue is with { provide: ReportService, useValue: mockReportService } using just ReportService will run fine but it means I cant run one of my tests. I want to create a spy object mockReportService = jasmine.createSpyObj(['getReport']);.

The error that you will see in the StackBlitz is that TypeError: Cannot read property 'subscribe' of undefined.

If somebody can help me getting this to run with a mockservice so I can test the getReport subscribe function I would be most grateful.

Upvotes: 2

Views: 3456

Answers (1)

Arnaud Denoyelle
Arnaud Denoyelle

Reputation: 31245

The problem comes from a misuse of jasmine.createSpyObj You have 2 options :

  1. Use jasmine.createSpyObj but in the right way :
// Note the first arg, you were missing it
mockReportService = jasmine.createSpyObj(ReportService, ['getReport']);


// Then, explain what to do with it :
beforeEach(() => {
  [...]
  // When called, make it return an Observable so that the call to subscribe() succeeds
  mockReportService.getReport.and.returnValue(of({}));
  fixture.detectChanges();
});
  1. Do not use spies

Sure, spies are neat but they are useful only if you want to change the returned values during the different unit tests. If you just need to always return a value, no matter which, you can opt for a hardcoded object like this :

  const mockReportService = {
    getReport: () => of({})
  }

  providers: [
    { provide: ReportService, useValue: mockReportService },

Upvotes: 4

Related Questions