Angular: Develop Faster with Prototyping

Prototyping for faster development & testing in Angular

Erxk
ITNEXT

--

About Me 👋

I currently work as a Software Engineer, alongside some of the best Angular developers in the industry, at the Fortune 100 company Cisco. I actively work on side projects in my free-time, which are powered by Angular & Firebase.

🔥 Source Code — Alternatively, each gist has a link to it’s corresponding file

Objectives 🗺️

  • 🦠 Maintain a universal set of mock data
  • 🧬 Share mock data between e2e (cypress) and unit (jest) tests
  • 🧙‍♂️ Efficiently create mock data for prototyping & testing
  • 🧪 Edits and deletes don’t affect live data
  • 🔭 Conveniently stub HTTP requests

Prototyping is when we utilize some sample or mock data to test out an idea quickly. Whenever I start a new project, the first thing I do is setup the architecture to prototype effectively. — Not to be confused with JavaScript Prototypes 🙂

This can be useful when

  • 🐇 Quickly proof of concept of an idea without affecting live data
  • 🖥️ The corresponding API isn’t setup on the backend yet
  • 🧪 Utilize realistic data for unit and e2e testing

As a bonus, this setup will enable us to use one set of mock data for all of our manual, unit, and e2e testing. — This means that we won’t have to create json fixtures for e2e tests and can utilize the same data from our manual testing.

Installation 🔧

The following only works when leveraging HttpClient. If you’re utilizing Angular & Firebase see Angular Prototyping: Firebase Emulator & Cypress.

Install the Angular in Memory API:

npm i angular-in-memory-web-api

What is the Angular In Memory API?

It’s essentially a fake backend that runs on your machine and knows how to mock HttpClient to return data from an Angular Service.

This article will focus on how to use it for prototyping & testing, and not a deep dive into the library itself.

Configuration ⚙️

Create an Angular Service to manage prototype data.

SOURCE

The above configuration gives us the ability to:

  • get all tickets via httpClient.get('api/tickets')
  • get a ticket via httpClient.get('api/tickets/ID')
  • delete a ticket via httpClient.delete('api/tickets/ID')
  • update a ticket via httpClient.put('api/tickets/ID', DATA)

To setup the service, we need to import it in our app.module and add a flag to determine if it should be on or off. — It’s recommended to add a flag to your environment file to determine if the In-Memory API should be on or off.

SOURCE

To keep this article short and to the point, I’ve created a short separate companion article in case you’re not sure how to setup a custom environment. — This allows us to have separate dev, prod, and prototype environments

Usage

To run your project with the In-Memory API on. (💡 prototype is the name of my custom environment. This will be whatever you have named it)

// Nx Project
nx run APP:serve:prototype
// Without Nx
ng serve configuration=prototype

The following code is a simple example to see our emulator working.

  • 🧙 Calls http.get(‘api/tickets’) on init (Which hits the In Memory API)
  • 🔋 Sets tickets to the response from the In Memory API
  • 🌈 Loops over the tickets in the template and displays ticket values.
COMPONENT-SOURCE | SERVICE-SOURCE

The next sections will look at using the same dataset we just used, in our unit and e2e tests.

Using in Jest (Unit Tests) 🃏

We’ll setup our test by adding HttpClientInMemoryWebApiModule to our TestBed, similar to how we set it up in our app.module. Notice, we don’t have to add mocks or stub requests to HttpClient in the test file.

In our InMemoryDatabaseService, I’ve defined 5 tickets. We’ll use the same component from the previous section. Recall that the component invoked http.get(‘tickets’) in ngOnInit. We expect the component to return all 5 tickets on init.

SOURCE
// NX
nx run YOUR_APP:test
// Without NX
npm run test
All 5 Tickets Returned

This provides a few benefits when testing.

  • 🧼 Automatically handle setting up and tearing down data
  • 🧙 Call our component directly without explicitly creating mocks
  • 🦠 Swap out datasets simply by using another service

When working in large teams I’ve seen a mixture of strategies for organizing mock data: JSON fixtures, large Javascript files, in-lining mock data in the spec file — This workflow makes it clear where the mock data should live, providing an organizational benefit to teams.

This example is very basic, but as a testimony, I used this strategy extensively on a professional project years ago where I had the ability to make architectural decisions like this. — In my opinion, it works even in complex applications because the In Memory API has so much flexibility.

Using in Cypress (E2E Tests*) 🌳

To run Cypress with the In Memory API on, we need to point to the prototype configuration/environment while running Cypress.

For non-Nx projects, I usually run ng serve --configuration="YOUR_ENV" and then run cypress open separately.

For Nx projects, in your APP-e2e project.json set devServerTarget to your prototype environment name [source] [how to setup a custom environment]

"devServerTarget": "APP:serve:prototype"

Now Cypress should run using the In-Memory API:

nx run APP-e2e:e2e --watch

I use this strategy for all of my side-project E2E testing. The following example below uses 0 json fixtures and 0 cypress intercepts. — This has helped me significantly in my projects to prototype new ideas, test features, and maintain useful mock data.

E2E Example

Conclusion

A good prototyping workflow is essential to me as a developer. The content listed here has no hard-and-fast rules. Use these tools in a way that fits your workflow.

I took a long hiatus from writing articles and have been doing a ton of work with: Angular, Firebase, Neovim, Linux, and Lua. If there’s anything you’d like to hear me elaborate on, or a specific topic from that list, let me know in the comments!

References

*Caveat, E2E is used broadly here. Technically, I would call this “Functional” testing, as it does not hit a live backend.

☁️ Flotes — Try the demo, no login required. Or sign up for free. Flotes is how I take notes and learn efficiently, even when I’m busy.

Flotes

--

--