1

Suppose there are 2 components : AppComponent and TestComponent. I am calling TestComponent using it's directive in the HTML template of AppComponent. Now TestComponent has an @Input() property ( let it be myTitle ).

I am doing unit testing for TestComponent only. For title, i am passing a random value in the test itself. Here is the code for the same :

app.component.html

<span><app-test [myTitle]="title"></app-test></span>

app.component.ts

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})

export class AppComponent{
    title = {name: 'hello-world'};
}

test.component.html

<p>test works!!{{myTitle.name}}</p>

test.component.ts

@Component({
    selector: 'app-test',
    templateUrl: './test.component.html',
    styleUrls: ['./test.component.css']
})

export class TestComponent implements OnInit{
    @Input() myTitle;

    constructor(){

    }

    ngOnInit():void{
        this.myTitle.name = "Hi!!";
    }
}

test.component.spec.ts

describe('Test component',() =>{
    let temp;
    let component: TestComponent;
    let fixture: ComponentFixture<TestComponent>;

    beforeEach(async(() =>{
       TestBed.configureTestingModule({
           declarations: [TestComponent],
           schemas: [NO_ERRORS_SCHEMA]
       }) 
       .compileComponents();
    }));

    beforeEach(()=>{
        temp = {name: "Heloooo"};
       fixture = TestBed.createComponent(TestComponent);
       component = fixture.componentInstance;
    });

    it('should check First',()=>{
       component.myTitle = temp;
       console.log(component.myTitle.name);
       console.log(temp.name);

       fixture.detectChanges();

       console.log(component.myTitle.name);
       console.log(temp.name);
       expect(component.myTitle.name).toEqual(temp.name);
    });

    it('should check Second',()=>{
       component.myTitle = temp;
       console.log(component.myTitle.name);
       console.log(temp.name);

       fixture.detectChanges();

       temp.name = "Majin Buu";
       console.log(component.myTitle.name);
       console.log(temp.name);
       expect(component.myTitle.name).toEqual(temp.name);
    });
});

Both the test passes and I don't know the reason why.

Questions:

  1. Here suppose the input property is a simple string instead of an object, then the cases fail, which is what i was expecting. But for objects it is not working.

  2. The console.log which i wrote gives the following output:

Test Case 1:

Heloooo          
Heloooo               
Hi!!          
Hi!!      

Test Case 2:

Heloooo       
Heloooo             
Majin Buu     
Majin Buu     

How come it is showing latest value for object.name? I thought that the object

temp

is local to this scenario.

  1. Does fixture.detectChanges() only calls ngOnInit? If no, then how does it work? And how to make sure that the test cases fail for objects too?

I am new to this community, so please help me improve the question if there are any fails.

0

1 Answer 1

2

When you assign an object to another object. Only reference changes not the heap address of that object.

So here temp is an object, which you are assigning to myTitle, myTitle and temp both referring same object means any change in that object will reflect by both myTitle and temp.

In test case 2, when you are changing temp value, you are updating value of object which is also referred by myTitle. That's why its getting passed

temp: object | Array // will get change properties value
temp:number | string | boolean // will not change.
  1. fixture.detectChanges() doesn't mean running ngOnInit(). It is used to tell Angular to run change detection
Sign up to request clarification or add additional context in comments.

8 Comments

Thank you for answering. But i wanted to know that after fixture.detectChanges() i am updating the temp object in the second test case, how that change is also reflected? Also i did not pass anything from parent to child, i am only testing the child... And please answer my last question also.
Thanks a lot. I wanted to know one more thing, that on calling fixture.detectChanges() the line inside ngOnInit() gets called twice as per the code coverage results. Why is it so? And how does it exactly checks for change detection, can it call ngOnChanges() also ?
It should call 2 times. Are you considering after running both tests? You can read from here angular.io/guide/testing#detectchanges
No Gaurav, not related to this. But related to unit testing.. Thank you
Can you close this then?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.