Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 5: How do I deal with the dependencies of the dependencies of a component while unit testing?

I'm new to unit testing in the context of an Angular 5 application. And right now, I'm trying to unit test a basic component.

The component is called CardComponent, and within the HTML of this component, I call the CheckboxComponent.
So here's the HTML of the CardComponent:

<div>
    <p>Test</p>
    <jg-checkbox [label]="'Test label'"></jg-checkbox>
</div>

As you can see, there's nothing complicated going on.

However, the CheckboxComponent does inject a service. For the sake of this question, I'll just call it TestService.

So when I unit test my CardComponent, here's my testbed:

TestBed.configureTestingModule({
    declarations: [
        CheckboxComponent
    ]
}).compileComponents();

Then I run this test:

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

This is just the default test that gets created through the CLI.

But now, it complains that there's no provider for the TestService. Am I really supposed to inject (and mock/spy) that as well?

That seems a bit backwards because I only care about the CardComponent, I shouldn't have to care about the CheckboxComponent, right? That's the whole point of unit testing.

Otherwise, since Angular has hierarchical components, I might have to go down many levels deep as my app grows.

This can't be right.

Can someone please help with this issue? I appreciate the help!

like image 602
gjvatsalya Avatar asked Apr 12 '18 19:04

gjvatsalya


People also ask

Which TestBed method is used to create an Angular component under test?

This is the first spec of the test suite and tests to see if the component compiles correctly. The TestBed. createComponent() method is used to create an instance of the AppComponent. The spec then uses expect and matcher functions to see if the component produces the expected behavior.

What is SpyOn in Angular unit testing?

SpyOn is a Jasmine feature that allows dynamically intercepting the calls to a function and change its result.

What is fixture detectChanges ()?

fixture is a wrapper for our component's environment so we can control things like change detection. To trigger change detection we call the function fixture.detectChanges() , now we can update our test spec to: Copy it('login button hidden when the user is authenticated', () => { expect(el. nativeElement.

What is Componentfixture in Angular testing?

You can create a component fixture with TestBed. createComponent . Fixtures have access to a debugElement , which will give you access to the internals of the component fixture. Change detection isn't done automatically, so you'll call detectChanges on a fixture to tell Angular to run change detection.


1 Answers

If there's no need to reference the CheckboxComponent in the CardComponent, there are two approaches:

  • the CheckboxComponent can be stubbed
  • NO_ERRORS_SCHEMA can be used in TestBed.configureTestingModule({})

The documentation has a section about Nested component tests

There is also an answer concerning Shallow component tests

Stubbing

Create a stub component in card.component.spec.ts.

@Component({selector: 'jg-checkbox', template: ''})
class CheckboxStubComponent {}

Then declare this in TestBed.configureTestingModule({}).

TestBed.configureTestingModule({
  declarations: [
    CardComponent,
    CheckboxStubComponent
  ]
})

NO_ERRORS_SCHEMA

NO_ERRORS_SCHEMA can be used instead of stubs.

TestBed.configureTestingModule({
  declarations: [
    CardComponent
  ],
  schemas: [ NO_ERRORS_SCHEMA ]
})

The NO_ERRORS_SCHEMA tells the Angular compiler to ignore unrecognized elements and attributes.

Either approach is acceptable. However, the documentation has a warning about overusing NO_ERRORS_SCHEMA.

The NO_ERRORS_SCHEMA also prevents the compiler from telling you about the missing components and attributes that you omitted inadvertently or misspelled. You could waste hours chasing phantom bugs that the compiler would have caught in an instant.

It also mentions that stubs have an additional advantage.

The stub component approach has another advantage. While the stubs in this example were empty, you could give them stripped-down templates and classes if your tests need to interact with them in some way.

It goes on further to show how to use both approaches together depending on the needs of the test.

like image 62
josavish Avatar answered Sep 21 '22 23:09

josavish