Raedwald
Raedwald

Reputation: 48682

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.

Upvotes: 9

Views: 6610

Answers (2)

LosManos
LosManos

Reputation: 7692

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,
        ],
...

Upvotes: 3

Z. Bagley
Z. Bagley

Reputation: 9260

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"

Upvotes: 10

Related Questions