How to mock an @Input() object in angular2?

24,693

Solution 1

Just add it as a property of the component-under-test:

beforeEach(() => {
  const fixture = TestBed.createComponent(DriftInfoDisplayComponent);
  const drift = fixture.debugElement.componentInstance;
  const driftInfo: DriftInfo = new DriftInfo();
  drift.inputInfo = driftInfo;
});

it('should have input info', () => {
  expect(drift.driftInfo instanceof DriftInfo).toBeTruthy();
)};

Solution 2

Stub an object, for example:

const InputInfo = {
      headerText: 'headerText',
      informationText: 'informationText',
      linkText: 'linkText',
      visible: 'visible' };

Assign it the component property in your synchronous before each:

beforeEach(() => {
  fixture = TestBed.createComponent(DriftInfoDisplayComponent);
  element = fixture.debugElement.nativeElement;
  component = fixture.debugElement.componentInstance;
  component.inputInfo = InputInfo; // Assign stub to component property
  fixture.detectChanges(); // calls NgOnit  
});

Test your template:

it('should have a header', () => {
 const header = element.querySelector('h1').textContent;

 expect(header).toBe('headerText');
});
Share:
24,693

Related videos on Youtube

Dan
Author by

Dan

Updated on July 09, 2022

Comments

  • Dan
    Dan almost 2 years

    I have looked on the angular2 website, as well as checked many SO posts and I could not find an example that illustrates my use case.

    I want to mock data from an object that has an @Input() tag. My component looks like this:

        ...
        export class DriftInfoDisplayComponent implements OnInit {
        
          showThisDriftInfo:boolean;
          headerText:string;
          informationText:string;
          linkText:string;
          @Input() inputInfo:DriftInfo;
        
          constructor(){}
        
          ngOnInit() {
            this.headerText = this.inputInfo.headerText;
            this.informationText = this.inputInfo.informationText;
            this.linkText = this.inputInfo.linkText;
            this.showThisDriftInfo = this.inputInfo.visible;
          }
        
          toggleDriftInfo(){
            this.showThisDriftInfo = ! this.showThisDriftInfo;
          }
        }
    

    My unit test file for this component looks like this:

        describe('DriftInfoComponent', () => {
          let component: DriftInfoDisplayComponent;
          let fixture: ComponentFixture<DriftInfoDisplayComponent>;
        
        
          beforeEach(async(() => {
            TestBed.configureTestingModule({
              declarations: [ DriftInfoDisplayComponent ]
            })
            .compileComponents();
          }));
        
          beforeEach(() => {
            fixture = TestBed.createComponent(DriftInfoDisplayComponent);
            component = fixture.componentInstance;
            fixture.detectChanges();
          });
        
          it('should create', () => {
            const fixture = TestBed.createComponent(DriftInfoDisplayComponent);
            const drift = fixture.debugElement.componentInstance;
            expect(drift).toBeTruthy();
          });
        });
    

    I would like to write a test that mocks the inputInfo:DriftInfo and its object in DriftInfoDisplayComponent and its properties so that I can test that this data is being displayed properly in the html template. How can I do this?

    Thanks for any help that may be provided!

  • Dan
    Dan about 7 years
    Thanks! Just a question. I have been using By.css to try and select an html element from the template, to check that the data of this object is being binded to the html template in the proper place. My question is... Is this a waste of time to be checking the html template like this? Or is this better suited for integration tests, and the point of karma/jasmine is to test the actual logic existed in the component file?
  • joh04667
    joh04667 about 7 years
    I would say that actually checking the data in the html object could fall in the realm of unit testing and be appropriate for karma/jasmine, but I also agree that it's sort of a pain. At my shop, we leave any testing that involves the view up to end-to-end tests (using protractor, which is also set up out of the box with Angular CLI generated projects)
  • Deepak Patidar
    Deepak Patidar over 3 years
    @joh04667 What if the input property is defined as readonly in child component do we have any other way to set mock data on that property
  • joh04667
    joh04667 over 3 years
    I'd question why an Input is marked as readonly when change detection can update that property at any time. Either way, it's just a compilation check, get around it by casting or string indexing, depending on your tsconfig settings: (comp as any).property = true; comp['property'] = true