Why you shouldn’t (over)use NO_ERRORS_SCHEMA in Angular Unit Tests

Isolation of a component for shallow unit testing requires a large amount of boilerplate if your component is a container for many other components/services. One shortcut to having to import and mock at least first-level dependencies is to use NO_ERRORS_SCHEMA.

Use of NO_ERRORS_SCHEMA

What is NO_ERRORS_SCHEMA telling the TestBed to do? Basically, ignore any template errors. So, when it hits your <my-child-component> tag, you don’t have to import MyChildComponent into your TestBed in your spec file. Angular will just treat that tag like any old div and continue on its way. In the above example you don’t need to import any of the child components of MyParentComponent.

However, there’s a big gotcha! It also will ignore unknown attributes; both property bindings and event handlers. Here is an example:

See anything wrong? You might not. And if you didn’t also write MyChildComponent then you might not know it.

Now you can see the problem. The bindings in MyParentComponent are to [item] not items and (clicked) not click. But your unit tests will still compile! They’ll even run!

ng build --prod will catch the property binding problem, [item], but will not catch the misnamed (clicked) handler. The only way to find that one is in integration testing!

NO_ERRORS_SCHEMA is using a sledgehammer to kill a fly. It’s so overpowering that it could be causing damage.

So, how do we isolate our components from their dependencies without opening ourselves up to errors in our template?

Mocking is one solution. Mock all of your first-level dependencies. But, for large container components (smart components), this can be tantamount to importing a whole NgModule. (I admit I’ve resorted to this in the past…)

The Angular documentation suggests a hybrid approach using NO_ERRORS_SCHEMA along with mocking child components. Deciding which to mock and which to ignore is at the developer’s discretion. It may be that NO_ERRORS_SCHEMA is okay for mocking some of your 3rd-party dependencies, like Angular Material? But you’ll need to make that decision for yourself.

One way of easily mocking dependencies is to use ng-mocks. This makes mocking child components, as well as many other common mocks, rather easy:

MockComponents(ChildOneComponent, ChildTwoComponent)

There is more to ng-mocks than I can cover in this article, so I leave that to you. But the point remains, mocking your child components to produce shallow unit tests is a much safer approach than a broad use of NO_ERRORS_SCHEMA.

--

--

Passionate about JavaScript and Angular. Pure front-end development for the past eight years or so…

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store