Testing a Component in Angular
Overview
A component combines an HTML template with a TypeScript class, in contrast to all other elements of an Angular application. The class and the template working together is what make the component. A component should be tested to ensure that it functions with other components in the desired manner.
To do these tests, it is necessary to create the component's host element in the browser DOM, like Angular does, and look at how the component class interacts with the DOM as specified by its template.
Introduction to Testing Components
The term spec is included in the filenames of test files in the Angular CLI to make it simpler for the Karma runner to locate and execute them.
A test's filename consists mostly of the name of the Angular item it is intended to test, followed by the suffix.spec.ts.
The test file for the main Angular app component, app.component.ts, for instance, would be app.component.spec.ts and would be located in the same directory as the component file.
The two functions we utilize most frequently while writing tests are described and provided by Jasmine's testing framework. We use to describe to create a spec or a test as well as a suite, which is a collection of connected tests.
- describe(): It’s a suite of tests
- it(): Declaration of a single test
- expect(): Expect something to be true.
Component Class Testing
Testing for component classes should be kept extremely tidy and straightforward. It should be just to test one unit. You should be to be able to tell what the test is testing from the outset.
File: user-avatar.component.html
File: user-avatar.component.spec.ts
Output
Component DOM Testing
A component consists of more than just its class. A component communicates with both other components and the DOM.
You can learn about class behavior via the class-only tests. They cannot provide information on whether a component will render correctly, react to user input and gestures, or integrate with its parent and child components.
None of the previous class-only tests were able to provide definitive answers regarding how the components operated on screens.
- Is UserAvatarComponent.uploadImage() bound to anything such that the user can invoke it?
- Is the UserAvatarComponent.message displayed?
- Is the image displayed as expected?
Given the earlier simple components that were demonstrated, these queries might not be troubling. However, a lot of components have intricate relationships with the DOM elements detailed in their templates, which makes HTML appear and vanish in response to changes in the component state.
You must create the DOM elements linked to the components to respond to these kinds of queries, check the DOM to ensure that component state displays correctly at the appropriate times, and simulate user interaction with the screen to ascertain whether those interactions cause the component to behave as expected.
Component with a Dependency
Service dependencies are common among components.
Here in the example, we can see UserService is injected to upload an image.
File: user-avatar.component.ts
The UserAvatarComponent has decision logic that interacts with the service, logic that makes this component worth testing. Here's the testing module configuration for the spec file:
File: user-avatar.component.spec.ts
This time, the setup adds a UserService provider to the list of providers in addition to defining the component-under-test. but, not the actual UserService
Provide Service Test Doubles
Real services don't have to be introduced into a component-under-test. Test duplicates like stubs, fakes, spies, or mocks are frequently preferable. Real services can cause problems, but the goal of the specification is to verify the component, not the service.
The genuine UserService injection might be a nightmare. The genuine service may attempt to contact an authentication server and request the user's login information. It can be challenging to predict these actions. Making and registering a test duplicate in place of the actual UserService is simpler and safer.
The UserAvatarComponent and its tests require a minimum mock of the UserService, which this test suite provides:
File: user-avatar.component.spec.ts
Component with Inputs and Outputs
Usually, a component with inputs and outputs can be found inside the host component's view template. The host employs property bindings to set the input property and listen to events generated by the output property.
The testing aims to confirm that these bindings perform as intended. Set input values and keep an eye out for output events in the tests.
Conclusion
- Angular applications come with Karma test runner
- To run the test ng test command is used
- A component is made up of various components, such as a class, DOM, dependencies, etc., so when developing tests, we must consider all of those factors.