Tech Blog

More on Testing Cloud Apps

In a previous blog post, we learned how to get started with testing Cloud Apps. Since Cloud Apps are written in Angular, they can be tested using the standard toolset, including Jasmine and Karma. Like with any code project, an automated test suite helps to improve quality and prevent regressions, allowing us to make changes in the future with more confidence.

In this post, we’ll implement tests for the main component in the scaffolding provided with a newly initialized Cloud App. By doing so, we’ll learn a bit more about testing Cloud Apps, and pick up a few tips along the way.

While working on this post, we updated the main.component.html template in the scaffolding to remove some extraneous async pipes, thereby making the code more efficient and more testable. We’re always learning and striving to improve, just like you! To run this example, be sure you’re working with version 1.4.2 of the CLI or above.

Looking at the scaffolding, we see that provides some basic functionality that exercises some core Cloud App API features. Thinking of test cases, we came up with the following. The MainComponent should…

  • show a list of entities
  • display entity selected
  • call REST API when entity selected
  • populate text area with data
  • call POST API when update button clicked
  • show welcome message when no entities

Let’s build a test suite which validates these assertions.

Getting Started

We’ll start by creating a new file in the main component folder called main.component.spec.ts. We’ll copy the basic test module configuration from the Testing Cloud Apps documentation, and then replace the instances of “TestComponent” with “MainComponent”. Then we’ll run the eca test command to make sure everything is set up correctly. If we get a green result for the “should create” test, we’re ready for move on.

Test #1

The first test we’ll add will validate that a list of entities is displayed. One of the tenets of testing is isolation- we don’t want to have any external dependencies. So we’ll need to replicate the behavior of Alma when a page with entities is displayed. For this we’ll use a mock service instead of the CloudAppEventsService.  The mock service provides a way for us to simulate navigating to a page in Alma. We’ve placed the mock and other constants into a separate file for reuse:

cloud-app-testing.tsView on Github

We need to add our mock service in the providers property of our test module configuration. And since most of our tests rely on there being a list of entities, we add a beforeEach method which loads the entities and calls detectChanges to trigger change detection in the template:

main.component.spec.tsView on Github

Finally, we add a reference to the Angular Material test harnesses. These classes enable our tests to easily interact with the Material controls in our template. For example, in this test we get a reference to all of the material radio buttons using the MatRadioButtonHarness class. Then we verify that the number of radio buttons matches the number of entities in our mocked page.

main.component.spec.tsView on Github

Test #2

Next we’ll add a test which confirms that when we select an entity it is displayed in the template. Our test will use the component member selectedEntity, first confirming it’s not defined. Then we’ll use the same test harness we used above to “check” a radio button. We then verify the selectedEntity member is defined, and we use a test harness for material cards to confirm the entity is now displayed in the template.

main.component.spec.tsView on Github

However, when we first run our new test, we get an error:

Error: Timeout - Async function did not complete within 5000ms

This is because of another piece of functionality in the scaffolding. When an entity is selected, the component uses the CloudAppRestService to retrieve the data about the selected entity. Since our test module doesn’t have any knowledge of the rest service, the request times out. Now we’ll need another strategy to intercept calls to the rest service and supply a mock response. For this we’ll use a “spy”, which spies on requests to the specified service. We define our spy in the utility module:

cloud-app-testing.tsView on Github

And then define another beforeEach function to configure the spy.

main.component.spec.tsView on Github

Now our test passes successfully.

Test #3

In our next test, we want to ensure the rest API is called when the entity is selected. We can use the same spy we configured in the previous test. The spy supports a method called toHaveBeenCalledWith. We use that method to confirm the rest service was called with the link of the selected entity.

main.component.spec.tsView on Github

Tests #4-6

We’ve now have everything in place we need to complete our last three tests:

  • We confirm the text area in the template includes the results of the REST API call from the previous test
  • We confirm the REST API is called when the update button is clicked, using the test harness for material buttons to “click” and using our spy to confirm the API was called with the PUT method
  • We confirm the welcome message is displayed when there are no entities are shown, using the mock events service to simulate an empty entity list and checking for the existence of our h1 tag.
main.component.spec.tsView on Github

And there we have it- now we are confident that we’ve fully validated the functionality of our scaffolding, using mock services, spies, and material test harnesses to build robust and efficient tests.

Click below to view a video which walks through this blog post:
32:51

Leave a Reply