So far, we've seen how to automatically mock all dependencies of a service in order to test it in isolation. Testing a component is mostly the same, but we also need to render the template and mock the components used in that template.
tl;dr: jump directly to the recap for the full code example.
It is good practice to create a page object for component tests. The page object abstracts away the selectors to access elements rendered by the template and exposes a nice interface for the tests.
NgVcuum provides a utility class to simplify the setup of the page object
renderComponent internally invokes shallow-render to create a shallow rendering of the component, and takes care of creating an omnimock for each of the component's service dependencies.
If you would like to get a reference to the Shallow instance, to apply advanced customizations and to bind data, you can use getShallow instead.
// Use page object to locate login button, and click.
page.loginButton.click();
}));
note
Always wrap component tests with fakeAsync.
Angular buffers internal operations in unredictible ways and so you need to be able to control the passage of time, otherwise you may experience weird and frustrating behavior.
If we try to run this test, we get the following error:
Indeed, MyComponent is trying to access AuthService.isAuthenticated during rendering to determine if the user is authenticated and, ultimately, to know what to render.
We need to specify the behavior of AuthServicebefore rendering the component.
Let's do this. We move the mock behavior to the beforeEach function:
beforeEach(fakeAsync(()=>{
when(getMock(AuthService).authenticated).return(false);// Add here
This is the thing that we are actually testing for! Let's write an expectation for this call. Remember to use the quantifier .once() to tell omnimock that you expect this call to happen exactly once.
We also add expect().nothing() so that jasmine stops complaining about the fact that your test doesn't contain an actual expectation.
it('lets user log in when not authenticated',fakeAsync(()=>{
The full code of the test is given at the bottom of this page. But first, let's add a second test case
#Write another test (trick to customize component setup)
In the previous section, we've hardcoded the fact that the user is not authenticated. But what if we would like to test when the user is authenticated?
This is exactly what we will do. We first replace the hardcoded answer with a getter and declare a value that we can access to modify the behavior.
Now, we can add a second test which asserts what happens when the user is authenticated.
Remember that the component is shallow rendered. This means that <app-fancy-button> in the component template is not expanded.
We treat it like a black box and simulate its behavior by emitting a click event directly from the test suite. This is what makes the test of MyComponent completely decoupled from the implementation of FancyButtonComponent.
it('presents a fancy button when authenticated',fakeAsync(()=>{