0

Okay. So I have a component called "Account" which uses @select() to make user$. The type of user$ is an Observable with the interface of "User"

@select user$: Observable<User>

I also have a variable called 'user'. In the constructor of this component, I subscribe to "user$", and derive the properties of 'user' from the observable.

constructor(private ngRedux: NgRedux<gdcClientState>, private dbService: DatabaseService){
 this.user$.subscribe(user => this.user = user)
}

This works great in practice, but when I try to test I immediately get hit with an error about how it can't read 'firstName' of undefined. *one of the properties set into 'user' by the observable 'user$' is a firstName.

Here is what my test looks like:

/* tslint:disable:no-unused-variable */
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import {NgReduxTestingModule, MockNgRedux} from '@angular-redux/store/testing';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { DatabaseService } from '../database.service';
import { User } from '../user'; 
import { Observable } from 'rxjs';

import { AccountComponent } from './account.component';

describe('AccountComponent', () => {
  let component: AccountComponent;
  let fixture: ComponentFixture<AccountComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ AccountComponent ],
      imports: [NgReduxTestingModule, FormsModule, ReactiveFormsModule],
      providers: [
        {provide: DatabaseService}
      ]
    })
    .compileComponents();
  }));


  beforeEach(()=>{
    MockNgRedux.reset();

    fixture = TestBed.createComponent(AccountComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();

  });

  afterEach(()=>{
    fixture.destroy();
  })






  it('should create', async(() => {
    const fixture = TestBed.createComponent(AccountComponent);
    fixture.detectChanges();
    const compiled = fixture.debugElement.nativeElement;


 fixture.detectChanges();

    expect(compiled).toBeTruthy();
  }));
});

I tried implementing some fixes and suggestions from these two threads: Testing @select decorators with @angular-redux/store Testing Angular with @angular-redux/store in Storybook

But it didn't work out for me. I would love some help with this. Thank you.

1 Answers1

0

You shouldn´t initialize the subscription on the constructor of the Component, but on the ngOnInit lifecycle hook.

ngOnInit(){
 this.user$.subscribe(user => this.user = user)
}

In your spec, be sure you are initializing the user on your component before firing the first detectChanges. So better to create a mockUser and set it there:

    fixture = TestBed.createComponent(AccountComponent);
    component = fixture.componentInstance;
    component.user = mockUser;
    fixture.detectChanges();

Cheers!

MigueMike
  • 189
  • 6
  • You mean have this: @select user$: Observable inside of the constructor? And then I assume I would have this.user$.subscribe(user => this.user = user) following it? ((Sorry I'm on mobile)) – Adrian Rosales Oct 29 '19 at 20:48
  • @AdrianRosales I have edit my answer. You should initialize your subscription on the ngOnInit, not in the constructor – MigueMike Oct 29 '19 at 20:58
  • @AdrianRosales edited my answer again. initialize user variable of the component in your spec – MigueMike Oct 30 '19 at 07:09