Home > other >  Angular test: why do I get a ReferenceError while attempting to inject a mockService?
Angular test: why do I get a ReferenceError while attempting to inject a mockService?

Time:12-06

I'm using an Angular 14.2.0 project (created with ng cli, no change in tsconfig nor in angular.json).

I'm trying to write a simple test on a component which injects a service UserService.

I use jasmine.createSpyObj to mock the service, but as soon as I provide it in the TestBed module, I have this error:

 An error was thrown in afterAll
  Uncaught ReferenceError: Cannot access 'UserService' before initialization

This is really confusing, since I'm not trying to instantiate the service at all.

I commented the component creation to understand which piece of code is producing the error, and it confirms that the error is definitely triggered by the use of a provider for my mock service.

Here is the code that triggers the error :

describe('UserListContainerComponent', () => {
  beforeEach(async () => {
    const mockUserService = 
        jasmine.createSpyObj('UserService', [
          'getUsers'
        ]);
    mockUserService.getUsers.and.returnValue(of(profiles));

    await TestBed.configureTestingModule({
      declarations: [ UserListContainerComponent ],
      providers: [
        { provide: UserService, useValue: mockUserService }
      ]
    })
    .compileComponents();
  });
});

Error disappears as soon as I comment the "provide: UserService" line (but obviously, I won't go far in the component instanciation without it).

BTW, I also tried:

  • using a home-made mock object instead of a Jasmine Spy
  • using a class (and the useClass property).

In all cases, the error still shows up. I don't understand why it tries to instanciate the actual service.

Any idea of what I'm missing here ?

PS: I literally emptied my component, including the constructor and any reference to the service, to make sure it's not the cause. I still have the error with that component:

@Component({
  selector: 'app-user-list-container',
  templateUrl: './user-list-container.component.html',
  styleUrls: ['./user-list-container.component.css']
})
export class UserListContainerComponent {
  private _filteredUsers$ = new Subject<Person[]>();
}

CodePudding user response:

This shouldn't be happening and I can't explain why this error occurs. Can you try the following modification to see if the error goes away? I have noticed that spy objects are always created in the following way.

// !! Move declaration here
let mockUserService: jasmine.SpyObj<UserService>;
beforeEach(async () => {
    // !! Create a new spy object here
    mockUserService = 
        jasmine.createSpyObj<UserService>('UserService', [
          'getUsers'
        ]);
    // !! Mock the method here
    mockUserService.getUsers.and.returnValue(of(profiles));
    // !! Same TestBed.configureTestingModule

CodePudding user response:

You can alternatively try to spy on the service in the unit tests themselves to see if that works:

it('test', () => {
  const fixture = TestBed.createComponent(UserListContainerComponent);
  const component = fixture.debugElement.componentInstance;
  spyOn(component.userService, 'getUsers'); // userService name should be set to the variable name used in the UserListContainerComponent
}
  • Related