简体   繁体   中英

Angular Unit Testing - Mock Child Component using Stub

I am trying to unit test a component that has a child component that I want to mock. I don't want to use the NO_ERRORS_SCHEMA cause the drawbacks associated. I am trying to use a stub/dummy child component. The code is as follows:

parent.component.ts

@Component({
  selector: 'parent',
  template: `
    <!-- Does other things -->
    <child></child>
  `
})
export class ParentComponent { }

child.component.ts

@Component({
  selector: 'child',
  template: '<!-- Does something -->'
})
export class ChildComponent {
  @Input() input1: string;
  @Input() input2?: number;
}

parent.component.spec.ts

describe('ParentComponent', () => {
  let component: ParentComponent;
  let fixture: ComponentFixture<ParentComponent>;
  let router: Router;

  @Component({
    selector: 'child',
    template: '<div></div>'
  })
  class ChildStubComponent {
    @Input() input1: string;
    @Input() input2: number;
  }

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ ParentComponent, ChildStubComponent ],
      imports: [
        AppRoutingModule, HttpClientModule, BrowserAnimationsModule,
        RouterTestingModule.withRoutes(routes)
      ],
      schemas: [CUSTOM_ELEMENTS_SCHEMA]
    })
      .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(ParentComponent);
    component = fixture.componentInstance;
    router = TestBed.get(Router);
    spyOnProperty(router, 'url', 'get').and.returnValue('/somePath');
    fixture.detectChanges();
  });

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

The problem I'm having is that angular is complaining with the following error:

Failed: Template parse errors:
More than one component matched on this element.
Make sure that only one component's selector can match a given element.

I'm using Angular version 8 if that helps. Everywhere I looked so far shows that you stub a child component the same way I am doing now. Using ngMocks is not an option at the moment.

EDIT Tried using ngMock but this only has the same problem. Any help would be very much appreciated!

Solution

Got it working. Problem was that the AppRoutingModule had the real component imported already.

For the nested component, we can mock them like this: https://angular.io/guide/testing-components-scenarios#stubbing-unneeded-components

In conclusion, your parent.component.spec.ts should be:

import { HttpClientTestingModule} from '@angular/common/http/testing';
import { Component } from '@angular/core';

describe('ParentComponent', () => {
  let component: ParentComponent;
  let fixture: ComponentFixture<ParentComponent>;
  let router: Router;


 @Component({selector: 'child', template: ''})
 class ChildStubComponent {}

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ ParentComponent, ChildStubComponent ],
      imports: [
        AppRoutingModule, HttpClientTestingModule, BrowserAnimationsModule,
        RouterTestingModule.withRoutes(routes)
      ],
      schemas: [CUSTOM_ELEMENTS_SCHEMA]
    })
      .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(ParentComponent);
    component = fixture.componentInstance;
    router = TestBed.get(Router);
    spyOnProperty(router, 'url', 'get').and.returnValue('/somePath');
    fixture.detectChanges();
  });

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM