After adding the routing guards to your project, you need to unit test their methods to make sure that an unauthenticated user is correctly redirected to a
"/login" path. Check out a sample test configuration and test cases that verify if the router always redirects users unmistakably.
What we are going to build
We will add tests for checking if our
guard redirects users accordingly to the authentication result. The
guard in this example uses
AuthService to verify if users are logged in and
Router to redirect them to the login form if they are not.
Don’t worry if you don’t have a project like that. You can read the Securing your Spring Boot and Angular app with JWT #3 – Frontend post to see how to implement security features in an Angular app or just clone the little-pinecone/jwt-spring-boot-angular-scaffolding repository with a completed project (look into the
- Angular CLI – a command line interface tool that generates a project as well as performs many development tasks.
I’m working on
- An Angular project with a base
guardand authentication service implemented. This example requires the public
isLoggedIn()method in the service that returns a boolean value.
The AuthGuard implementation
guard that we are going to test was generated with the following command:
The source code that I written for it is placed in the snippet below:
I use the
AuthService to obtain the boolean value, on which the
guard decides whether to allow users to access the requested resources or redirect them to the login page. In case the users were not authorised they need to log in and, after that, are automatically redirected to the
url they tried to reach in the first place.
guard presented above implements the
canActivate() method and in the following sections we are going to test its logic.
Test the guard
When we created the
guard using the command mentioned above, the
Angular CLI generated the
auth.guard.spec.ts file for us. The main structure required for testing was automatically prepared and we even have one default test case already there –
checks whether the component can be properly instantiated.
|Run in the command line:to verify that all tests pass, before introducing any new code.|
The test configuration is resolved in thesection. To simplify the test cases to the maximum, we are going to define all required variables and mockups in advance. Furthermore, we need to slightly expand the section.
We are going to start with providing all variables that will be used during tests. You can see the list containing three objects and three mockups below:
To avoid manually creating instances of any classes we need, we are using the
TestBed as our
injector. Following there are declarations for the
AuthService and, obviously, the
Why we need the mockups?
CanActivate interface expects the following dependencies to be met:
Therefore, to properly test the
AuthGuard implementation we are going to use:
routeMock– to mock the
routeStateMock, to mock the
RouterStateSnapshotdependency used to obtain a protected path that a user tried to access –
'/cookies'is used in my app (adjust it accordingly to your application);
The last mockup,
routerMock, is used to create a spy on the
navigate() function to verify the correct work of redirection issued by our
Set the preconditions for each test
Now we are going to complete the prerequisites for tests. Keep in mind that we rely on the
TestBed to create classes and inject services. That ensures that every test will be run with all required objects provided. Instantiate the
guard like in the snippet below:
Don’t forget to specify that the guard in the tests is supposed to use the
routerMock declared earlier as the
Router instance. That allows us to spy on the
navigate() function. Make sure that you included the
HttpClientTestingModule in the
imports, without it the routing won’t work and the tests will fail.
Below you can see all the required imports for the
Add test cases
Let’s expand the default set of tests with additional cases.
First, let’s test the situation when an unauthorised user tried to access a path that is protected. The access should be denied and the user redirected to the login page:
If our private
checkLogin() function from the
guard works correctly, the router will navigate this devious user to the
'/login' page and the
guard.canActivate() function will return false.
The user authentication result returned from the
authService is false by default, so we didn’t have to mock it here. If the authentication service works differently in your app, don’t forget to mock its response here. Thanks to instantiating the service in the
beforeEach section, it is accessible in every test case.
On the other hand, we need to verify that the
guard will allow an authenticated user to access the protected route:
We mock the authentication result returned from the
authService to make sure it will be positive. We expect that the
guard will grant access to the requested resource (
Run the tests
Use the following command to start the tests:
And verify the results:
|The described tests should only be a part of a larger suite. To fully verify that the authorisation mechanisms in your application work properly, you need to cover more cases. You can find other tests in the project repository.|
The complete code for the
If you need more details about securing an Angular application I once again recommend the Securing your Spring Boot and Angular app with JWT #3 – Frontend post.