luca
luca

Reputation: 3328

Angular 6 component test with a variable into HTML

I'm new with Angular test and I have a problem. The first problem is with the variable username into a component that I use to show logged username into HTML page: This is the test file:

describe('HeaderComponent', () => {
  let component: HeaderComponent;
  let fixture: ComponentFixture<HeaderComponent>;
  let app;
  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ HeaderComponent, DialogListConfigurationComponent, DialogConfirmNewConfigurationComponent ],
      providers: [ MessageService, JwtHelperService, AuthService ],  
      imports: [ DialogModule, MenubarModule, FontAwesomeModule, RouterTestingModule, TreeModule, HttpClientTestingModule, JwtModule.forRoot({
        config: {
          tokenGetter: () => {
            return sessionStorage.getItem(environment.tokenName);
          },
          //Exclude this URL from JWT (doesn't add the authentication header)
          blacklistedRoutes: [
            '/api/login',
          ]
        }
      }), ]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(HeaderComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });
});

The component is this:

export class HeaderComponent implements OnInit {
  @Output() sidebarEvent = new EventEmitter();
  @Output() clickOkButtonListConfigurationsEvent = new EventEmitter();
  username: String = this.authService.decodeToken.username;
  items = [] as MenuItem[];
  dialogListConfigurationVisible: boolean = false;
  faUserCircle = faUserCircle;
  defaultConfigurations: Configuration[];
  configurationCreated: boolean = false;
  dialogConfirmCreationVisible: boolean = false;
  constructor(private configurationService: ConfigurationService, private authService: AuthService) {   }

  ngOnInit() {
  ...
  }

The auth service method:

get decodeToken(): Jwt {
  return this.jwtHelper.decodeToken(this.getSessionToken);
}

The should create test fails with TypeError: Cannot read property 'username' of null

Upvotes: 1

Views: 849

Answers (2)

Thatkookooguy
Thatkookooguy

Reputation: 7012

You need to Mock your AuthService since this is a component test.

you can do that by providing an object in the module initialization code

TestBed.configureTestingModule({
  declarations: [ HeaderComponent, DialogListConfigurationComponent, DialogConfirmNewConfigurationComponent ],
  providers: [
    MessageService,
    JwtHelperService,
    {provide: AuthService, useClass: AuthServiceMock} ],  
  imports: [ DialogModule, MenubarModule, FontAwesomeModule, RouterTestingModule, TreeModule, HttpClientTestingModule, JwtModule.forRoot({
    config: {
      tokenGetter: () => {
        return sessionStorage.getItem(environment.tokenName);
      },
      //Exclude this URL from JWT (doesn't add the authentication header)
      blacklistedRoutes: [
        '/api/login',
      ]
    }
  }), ]
})
.compileComponents();

the AuthServiceMock class should implement the same interface as the original one. it can be something like this:

export class AuthServiceMock {
  // ...
  decodeToken: {
    username: 'testUser'
  };
}

than, before creating the component, setup the mock class if you don't want to set a default inside the mock.

NOTE: you can do this last step without creating a mock, but that will break the separation of concerns in your tests.

beforeEach(() => {
    let authServiceMock: AuthServiceMock = TestBed.get(AuthService);
    authServiceMock.decodeToken = { username: 'anotheruser' };

    fixture = TestBed.createComponent(HeaderComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

This should allow for the HeaderComponent run the this.authService.decodedToken.username line.

As a guideline: need to mock dependencies that rely on outside data.

You might also be able to remove dependencies of the original AuthService if previously you included them in the test module initialization. for example, if JwtHelperService is only used internally for AuthService, the test module can exclude that provider.

Upvotes: 3

luca
luca

Reputation: 3328

From the @Thatkookooguy answer I got the problem and I add this two raw inside the beforeEach avoid so the use of mock object

const authService: AuthService = TestBed.get(AuthService);
authService.saveToken("token string");

Upvotes: 0

Related Questions