Let’s start with a very simple example. We have an aptly named component, ParentComponent , which includes another component, ChildComponent , in its template:

All ParentComponent is doing is rendering ChildComponent , which in turn renders the hard-coded list of children. Let’s write some code to test this component:

When we run the above test, it fails with the following error:

Failed: Template parse errors:

'child' is not a known element:

1. If 'child' is an Angular component, then verify that it is part of this module.

2. To allow any element add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component. (" <div>I am a parent. These are my children:</div>

This is Angular’s way of telling us that it doesn’t know about ChildComponent . What are our options here?

Solution 1. Add ChildComponent to declarations array

We can always add ChildComponent to the list of declared components:

Adding ChildComponent fixes the test, at the expense of test isolation

Sure enough, if we run the tests again, they succeed. Huzzah!

…not so fast. By doing this, we’ve broken Rule 1: Tests shalt be isolated. By declaring ChildComponent , our tests are now dependent on it to succeed. What happens if we add a dependency to ChildComponent ?

Let’s add Router as a dependency to ChildComponent

Given that we haven’t imported the RouterTestingModule into our unit tests, we’re not able to resolve Router , and the test is broken once more:

Error: StaticInjectorError(DynamicTestModule)[ChildComponent -> Router]:

StaticInjectorError(Platform: core)[ChildComponent -> Router]:

NullInjectorError: No provider for Router!

While we could always import RouterTestingModule , this is clearly an unideal solution. Changes to the internal logic of ChildComponent shouldn’t require us to modify ParentComponent unit tests. It’s annoying enough with 2 components — imagine how much worse it’ll be once we have 20, or 200.

Solution 2. NO_ERRORS_SCHEMA

If you did a Google search for the above error, you’ll probably come across quite a few Stack Overflow posts that recommend using NO_ERRORS_SCHEMA . It’s also recommended as an approach in the official Angular Testing Guide.

NO_ERRORS_SCHEMA tells the compiler to ignore any elements or attributes it isn’t familiar with. Let’s modify our example to use NO_ERRORS_SCHEMA :

Adding NO_ERRORS_SCHEMA instructs the compiler to ignore ChildComponent

After doing this, our test is working again 🙂. While this is a valid and widely used solution, it’s also one that leaves us vulnerable, as it violates Rule 2: Thou shalt alert us to broken templates. What happens if we misspell the <child> tag?

<child> intentionally misspelled as <chidl>

…the test still succeeds. This isn’t what we want. Even if we spelled <child> correctly, the tests will also succeed if we incorrectly spelled inputs: <child [childs]="children"></child> .

This is actually the approach we initially took when starting out with Sky Ledge. However, as the project grew in size and we began refactoring code, we quickly ran into situations where we didn’t realise there was something wrong until we actually ran the app. In one case, a broken component in an infrequently used part of the app remained broken for a couple of weeks until being discovered.

Beyond that, this approach also makes it very difficult to test @Input and @Output on child components. Let’s consider another approach.

Solution 3. Manually Mocking Components

We’ll extend our example to add inputs and outputs to ChildComponent :

Instead of ChildComponent having hardcoded names of children, we’ve made the child name an input. We’ve also added selected as an input: if child equals selected , we show a ❤️ next to that child (what better way to promote healthy sibling rivalry than choosing a favourite child?).

Output of the above code

So, how do we test ParentComponent now that ChildComponent is doing a bit more work? Another approach, also recommended in the Angular Testing Guide, is to manually mock (or stub) components. We can create a dummy ChildComponent and use that in place of the real ChildComponent . We just need to ensure that we give it the same selector:

Creating a stub component to use in place of the real component when testing

Now, in our fixture setup, we declare the stub component in place of the real one:

This now isolates testing of the ParentComponent from the internal workings of ChildComponent . For our purposes, we want to treat ChildComponent as a black box — we want to test that we’ve passed it the right inputs and that we handle any outputs it emits correctly. What it does with the inputs, and under what circumstances it emits outputs, is irrelevant to ParentComponent (testing of that logic should happen within the ChildComponent tests).

So, let’s write tests to ensure the inputs and outputs are behaving as expected:

Stubbing ChildComponent makes it easy to write detailed tests

Great. We’ve quickly and easily tested the functionality of ParentComponent and its interactions with ChildComponent . So are there any shortcomings with this approach?

The first shortcoming is that its quite verbose. Writing stub components for each component we want to mock can get tiresome very quickly, particularly if the components have lots of inputs and outputs. Here’s an extreme example from Sky Ledge (there’s so many inputs/outputs due to Rule 4 — Thou shalt prefer dumb components over smart components):

An example of a component with many inputs and outputs

Not only is it a pain in the proverbial to write a stub component for something like the above, it’s also prone to code rot (Shortcoming the Second). Let’s go back to ChildComponent . What if we wanted to rename child to something more descriptive, like childName ?

renaming child to childName

…our tests still succeed. We won’t know it’s actually failed until we run the application (or build it with Ahead-of-Time compilation enabled). The stub component approach requires us to remember to change the stub each time we change the real component. As you can expect, this is prone to human error and the problem exacerbates as your application grows.

Issues like these can make refactoring applications and maintaining unit tests a chore. Can we do better?

Solution 4. Mocking Components using NgMock

As it turns out, we can do better. There’s an excellent library called ngMocks which makes it trivial to create mock components (as well as directives and pipes). Instead of manually creating components, ngMocks automagically creates type-safe mocks for us, alleviating both shortcomings of Solution 3.

To get started, you’ll first need to install ngMocks:

npm install ng-mocks --save-dev

We no longer require ChildComponentStub so feel free to delete it. We’ll rewrite our tests to use ngMocks instead. First, let’s change the test config to automatically mock ChildComponent using ngMock’s MockComponent function:

Mock ChildComponent using MockComponent

We’ll also need to change our helper function to return ChildComponent instead of ChildComponentStub :

We’ll now get a bunch of compiler errors in our tests complaining that Property ‘child’ does not exist on type ‘ChildComponent’. So rename child to childName and run tests again.

And now…our tests are failing 🎊!

Failed: Template parse errors:

Can't bind to 'child' since it isn't a known property of 'child'.

(" a parent. These are my children:</div>

<child *ngFor="let child of children" [selected]="selected"

[ERROR ->][child]="child" (select)="onSelect($event)"></child>")

As MockComponent produces a strongly typed mock, we’re getting template errors that child doesn’t exist as an input on ChildComponent , exactly what we want. Let’s update ParentComponent template to use childName instead:

And just like that, all our tests are passing again.

Conclusion

Checkout a working demo of the final solution below: