0

In my service I have created a Subject 'allDataChange'

allDataChange = new Subject<AllData>();

In my component I have

ngOnInit() {
  ...
  this.detailsService.allDataChange.subscribe((data) => {
    ... something gets done here
  });
}

In my test... well I've got no clue what I'm doing, but whenever I run the test I see an errorTypeError: this.detailsService.allDataChange.subscribe is not function.

I've tried a dozen things. Well, it feels like a dozen. It may be that I've just tried the same thing 12 times. At this point, I don't know.

Here's the test setup and test:

describe('DetailsTabComponent', () => {
  let component: DetailsTabComponent;
  let fixture: ComponentFixture<DetailsTabComponent>;
  let appConfigServiceSpy: jasmine.SpyObj<AppConfigService>;
  let detailsServiceSpy: jasmine.SpyObj<RequisitionDetailsService>;

  beforeEach(async(() => {
    const spy = jasmine.createSpyObj('AppConfigService', ['loadAppConfig']);
    const detailsSpy = jasmine.createSpyObj('RequisitionDetailsService', ['getAllData', 'allDataChange']);
    TestBed.configureTestingModule({
      declarations: [
        DetailsTabComponent
      ],
      imports: [
        OwlDateTimeModule,
        OwlNativeDateTimeModule,
        HttpClientTestingModule
      ],
      providers: [
        {provide: AppConfigService, useValue: spy},
        {provide: RequisitionDetailsService, useValue: detailsSpy}
      ]
    })
    .compileComponents();
    appConfigServiceSpy = TestBed.get(AppConfigService);
    detailsServiceSpy = TestBed.get(RequisitionDetailsService);
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(DetailsTabComponent);
    detailsServiceSpy.getAllData.and.returnValue(goodData);
    // detailsServiceSpy.allDataChange.and.returnValue(goodData);
    component = fixture.componentInstance;
    fixture.detectChanges();
    fixture.debugElement.injector.get(RequisitionDetailsService);
  });

  it('should create', async(() => {
    const stubValue = 'http://test.test/';
    appConfigServiceSpy.loadAppConfig.and.returnValue(stubValue);
    expect(component).toBeTruthy();
  }));
});

I'm using Angular 6 and jasmine-core version 2.99.1. I've been trying to get this test to pass for two days, and the almighty Google has been absolutely no help. Can anyone tell me how to get past this 'blah.blah.subscribe is not a function error' and make this test pass?

1 Answers1

1

It looks pretty simple. You use jasmine spies to mock the services, so in the test, your component will get those instead of real services. The component doesn't really care what it is - all that it wants from whatever is injected is that thing should implement certain interface. Part of that interface is the property that returns observable that you subscribe to:

allDataChange = new Subject<AllData>();

But when you mock it with jasmine what you actually do is just put value in the property without observable:

detailsServiceSpy.allDataChange.and.returnValue(goodData);

So, that property effectively becomes just this:

detailsServiceSpy.allDataChange = goodData;

But wait, your component expects observable here! So, what you actually need to do is to put Observable there instead of just a value:

detailsServiceSpy.allDataChange.and.returnValue(of(goodData)); // <-- now that will be observable

But that is not all. Spying on the properties is actually done in slightly other way. Please refer to here for the details.

Alexander Leonov
  • 4,694
  • 1
  • 17
  • 25