angular 单元测试 - 没有父组件的提供者

angular unit test - no provider for parent component

我正在创建自己的 angular bootstrap library,目前我一直在为导航栏编写单元测试。

我提炼了 the troubled unit test down to the bare essentials 以下是摘要:

单元测试

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

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [
        RouterTestingModule.withRoutes([])
      ],
      declarations: [
        // Component to test
        BsNavbarDropdownComponent,

        // Mock components
        BsNavbarItemMockComponent,

        // Testbench
        BsNavbarDropdownTestComponent
      ],
      providers: [
        { provide: BsNavbarItemComponent, useClass: BsNavbarItemMockComponent }
      ]
    })
    .compileComponents();
  });

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

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

@Component({
  selector: 'bs-navbar-test',
  template: `
    <bs-navbar-item>
      <a [routerLink]='[]'>dropdown</a>
      <bs-navbar-dropdown>
        <bs-navbar-item>
          <a [routerLink]='["/b", "c"]'>bc</a>
        </bs-navbar-item>
      </bs-navbar-dropdown>
    </bs-navbar-item>`
})
class BsNavbarDropdownTestComponent {
}

@Component({
  selector: 'bs-navbar-item',
  template: `
  <li>
    <ng-content></ng-content>
  </li>`
})
class BsNavbarItemMockComponent {
}

待测单元

@Component({
  selector: 'bs-navbar-dropdown',
  templateUrl: './navbar-dropdown.component.html',
  styleUrls: ['./navbar-dropdown.component.scss']
})
export class BsNavbarDropdownComponent {

  constructor(
    @Host() @Inject(forwardRef(() => BsNavbarItemComponent)) navbarItem: BsNavbarItemComponent
  ) {
    this.navbarItem = navbarItem;
  }

  navbarItem: BsNavbarItemComponent;

}

BsNavbarDropdownTestComponent 中,显然 bs-navbar-dropdown (BsNavbarDropdownComponent) 有一个父标签 bs-navbar-item (BsNavbarItemMockComponent)。在要测试的单元中,我正在注入 BsNavbarItemComponent,它在作为 BsNavbarItemMockComponent.

提供的测试模块中

不过单元测试好像还是没有成功。

npm run nx run-many -- --target=test --projects=ng-bootstrap-demo --with-deps  --watch=false --browsers=ChromeHeadless

结果:

 FAIL   xxx-ng-bootstrap  libs/xxx-ng-bootstrap/src/lib/components/navbar/navbar-dropdown/navbar-dropdown.component.spec.ts
  ● BsNavbarDropdownComponent › should create

    NG0201: No provider for BsNavbarItemComponent found in NodeInjector. Find more at https://angular.io/errors/NG0201

同样,请注意该模块具有以下供应商:

providers: [
  { provide: BsNavbarItemComponent, useClass: BsNavbarItemMockComponent }
]

这有什么问题吗?为什么在单元测试中找不到 BsNavbarItemComponent 提供程序?

模块提供程序未被注入,因为 @Host 注入注解。

因此您的模拟组件应该可以通过原始组件令牌注入

@Component({
  selector: 'bs-navbar-item',
  template: `
  <li>
    <ng-content></ng-content>
  </li>`,
  providers: [provide: BsNavbarItemComponent, useExisting: forwardRef(() => BsNavbarItemMockComponent)]
})
class BsNavbarItemMockComponent {
}