2

I am working with a similar @Input to Angular2 @Input to a property with get/set. I have been having some trouble figuring out how to set up my unit tests though. Here is my component

get order(): any {
    return this._order;
}

@Input()
set order(value: any) {

    this._order = value;
}

Here is my test setup

 TestBed.configureTestingModule({
            declarations: [
                OrderDetailsComponent,
                OrdersGridComponent,
                KeyValuePipe
            ],
            schemas: [
                CUSTOM_ELEMENTS_SCHEMA
            ],
            providers: [
            ],
            imports: [
                // AppModule
            ]
        }).compileComponents();

With an additional before each where I define the component

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

Before I can run this simple test

 it("should set this.enable button to false", () => {
    component.signOrderFromOrderDetails();
    expect(component.signButtonEnable).toBe(false);
});

I am getting the error

TypeError: undefined is not an object (evaluating 'this._order.hasOwnProperty') in karma-test-shim.js (line 106886)

My initial was to create a mock order constant and assign it to my component inside of a before each like so...

  const order = {
    orderSections: [],
    patient: {}
  };
 component.order = order;

However, I am not allowed to make that assignment

TypeError: Attempted to assign to readonly property. in karma-test-shim.js (line 94033)

My next assumption is that I must need to mock the parent component OrdersGridComponent as OrdersDetails is the child. But if that is the case I am not seeing how to set that up in my unit test. Any feedback would be much appreciated.

Kamil Naja
  • 6,267
  • 6
  • 33
  • 47
Winnemucca
  • 3,309
  • 11
  • 37
  • 66
  • The last error you get is strange, since the property is not readonly. It's hard to comment about the first one without seeing the complete code of the component and the test. Anyway, you don't need an OrdersGridComponent as the parent. You might need a parent component, though, but it doesn't need to be an OrdersGridComponent. Any test component using the OrderDetailsComponent will do. It's also unclear why you have a getter and a setter, since they don't do anything that a regular public property would do. – JB Nizet Jan 08 '18 at 21:56
  • @JBNizet The getter and setter is a use good question. I did not write that part of the component so hopefully I can refactor it. But would the parent component just be an host that I would mock? – Winnemucca Jan 08 '18 at 22:09
  • It would be a component written just for your test, with the template and state you need to be able to test OrderDetailsComponent. Something like this: https://github.com/Ninja-Squad/globe42/blob/master/frontend/src/app/chart/chart.component.spec.ts#L7-L27, which is used to test the chart component with a valid input. – JB Nizet Jan 08 '18 at 22:12

1 Answers1

2

I'm pretty sure the magic is with async()

Component:

@Input()
set myVar(data: number) {
   this._myVar = data;
}

Test:

it('myVar input should set _myVar', async(() => {
  component.myVar = 42;
  expect(component._myVar).toBe(42);
}));
Boris Yakubchik
  • 3,861
  • 3
  • 34
  • 41