Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular Karma Jasmine test "Can't bind to 'ngIf' since it isn't a known property"

My Karma Jasmine tests of an Angular @Component complain that

ERROR: 'Can't bind to 'ngIf' since it isn't a known property of 'p'.'

When there is that kind of error for the application itself, the fix is to ensure you add BrowserModule to the imports: [] in the @NgModule() of your application module (app.module.ts). I indeed have that import (so this question is not a duplicate of that canonical question about "Can't bind to 'ngXXX' since it isn't a known property of 'YYY').

This is my test set-up code:

    let component: MyComponent;
    let fixture: ComponentFixture<MyComponent>;

    beforeEach(async () => {
        TestBed.configureTestingModule({
            imports: [
                BrowserModule
            ],
            providers: [
                MyComponent,
                { provide: MyService, useClass: MockMyService }
            ]
        }).compileComponents();
        TestBed.inject(MyService);
        component = TestBed.inject(MyComponent);
        fixture = TestBed.createComponent(MyComponent);
        fixture.detectChanges();
    });

My HTML template says *ngIf, not ngIf or a typo for that, which is another common cause of that error message:

<div class="self">
    <p *ngIf="isLoggedIn() else selfLogin">Logged in as
        {{getUsername()}}</p>
    <ng-template #selfLogin>
    <button id="login" (click)="login()">login</button>
    </ng-template>
</div>

Putting the test module configuration and object injection in separate beforeEach calls (as suggested for a different Angular testing problem) did not help.

like image 478
Raedwald Avatar asked Sep 09 '20 14:09

Raedwald


People also ask

Can't bind to since it isn't a known property?

What does "Can't bind to 'x' since it isn't a known property of 'y'" mean? link. This error often means that you haven't declared the directive "x" or haven't imported the NgModule to which "x" belongs. Perhaps you declared "x" in an application sub-module but forgot to export it.

Can't bind to ngFor since it isn't a known property?

ngFor is not a known property would mean for whatever reason, ngFor cannot be recognized in the application. However, the real problem was that ngFor was recognised but the syntax of ngFor was wrong. Anyway, let's hope Angular team improves their logging in future updates.


2 Answers

I see you're including the Component in your TestBed providers. Components are normally part of declarations. So, something like this:

    let fixture: ComponentFixture<MyComponent>;
    let component: MyComponent;

    beforeEach(waitForAsync(() => {
        TestBed.configureTestingModule({
            providers: [
                { provide: MyService, useClass: MockMyService }
            ],
            declarations: [
                MyComponent
            ]
        }).compileComponents();
    }));
    beforeEach(() => {
        TestBed.inject(MyService);
        fixture = TestBed.createComponent(SelfComponent);
        component = fixture.componentInstance;
        fixture.detectChanges();
    });

You also have a HTML formatting issue for your else declaration:

<div class="self">
    <p *ngIf="isLoggedIn() else selfLogin">Logged in as
        {{getUsername()}}</p>
    <ng-template #selfLogin>
    <button id="login" (click)="login()">login</button>
    </ng-template>
</div>

should be...

*ngIf="isLoggedIn(); else selfLogin"

like image 146
Z. Bagley Avatar answered Oct 20 '22 11:10

Z. Bagley


I got the same error due to me not including the component-under-test in the declarations.

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

  beforeEach(
    waitForAsync(() => {
      TestBed.configureTestingModule({
        declarations: [
          MyComponent, // <-What i forgot.
          OtherComponent,
        ],
...
like image 36
LosManos Avatar answered Oct 20 '22 11:10

LosManos