Skip to main content

How to fix TypeError: Cannot read property 'subscribe' of undefined

This issue means that something has been replaced with a mock object and returns a dummy result (undefined) instead of observable streams.

There is an answer for this error in the section called How to mock observables, if the error has been triggered by a mock service, and its property is of type of undefined.

Or you might check MockInstance or ngMocks.defaultMock in the case if the error has been caused by a mock component or a mock directive.

Angular Material UI​

If you are using ng-mocks with Angular Material UI, and you need to keep a mat module, but this causes TypeError: Cannot read properties of undefined (reading 'subscribe').

Highly likely, this means that under the hood the kept module is using a root provider which has been mocked, because ng-mocks mocks root providers by default.

To solve that, you have 2 options, skip mocking of root providers, or find out which mock provider causes the issue, and customize its mock to return Observable instead of undefined.

Skip mocking of root providers​

To skip mocking of root providers simply add .keep(NG_MOCKS_ROOT_PROVIDERS) to your MockBuilder definition:

import { MockBuilder, NG_MOCKS_ROOT_PROVIDERS } from 'ng-mocks';

describe('suite', () => {
beforeEach(() => MockBuilder(YourComponent, ItsModule)
.keep(MatBadgeModule) // or any other MatModule
.keep(NG_MOCKS_ROOT_PROVIDERS) // <- the fix
);
});

To customize a mock​

To customize a mock, you can use EMPTY and ngMocks.defaultMock:

src/test.ts
import { EMPTY } from 'rxjs';
import { ngMocks } from 'ng-mocks';

ngMocks.defaultMock(BreakpointObserver, () => ({
observe: jasmine.createSpy().and.returnValue(EMPTY),
}));