HarmonicaBlower
HarmonicaBlower

Reputation: 136

Test a method which calls another method from the viewChild using Jasmine

I have this method that validates the component and it's calling out to this another component which is it's ViewChild. I am using the component using this.ViewChildComponent.someMethod(); in the component which I am trying to test. I tried to use the spyOn(viewChildComponent, 'someMethod').and.returnValue(true). But it says the this.ViewChildComponent.someMethod() is undefined. I have all the dependencies such as services for the ViewChildComponent on the providers. I even went a step forward and made the call that the viewChildComponent makes to its service to decide someMethod();

Any help would be awesome.

Upvotes: 11

Views: 12742

Answers (2)

codeepic
codeepic

Reputation: 4132

@DanielDrozzel answer may solve your problem, but essentially it is flawed and not a good practice. I would like to offer an alternative. In Daniel's answer, when you use declarations: [ TestedComponent, ChildComp] you create a tight coupling in your unit tests between TestedComponent and ChildComp. If the child component stops working your tests will fail, if it changes behaviour, the tests may fail.

It's not always a bad thing, but it can sometimes bite you. It's better to use Component Stubs as mentioned in official Angular Docs https://angular.io/guide/testing#nested-component-tests or a very useful ng-mocks library. The third option mentioned in the Angular docks above is NO_ERRORS_SCHEMA but you can't use it if you want to test if child component's methods are called from parent.

Using ng-mocks library all you need to do is to swap

declarations: [ TestedComponent, ChildComp] in Daniel's answer for

declarations: [ TestedComponent, MockComponent(ChildComp)]

and the parent component can be tested without creating a hard dependency on a child component.

Upvotes: 6

Daniel Drozdzel
Daniel Drozdzel

Reputation: 154

If you have for example

class TestedComponent() {
     @ViewChild('ChildComp') public variableChildComponent: ChildComp;
}

In testing spec file declare child component and tested component:

beforeEach(() => {
  TestBed.configureTestingModule({
     declarations: [ TestedComponent, ChildComp]
  })
  fixture = TestBed.createComponent(TestedComponent);
  comp = fixture.componentInstance;
  spyOn(comp.variableChildComponent, 'someMethod').and.returnValue(true);
});

This should work.

Upvotes: 10

Related Questions