Blog / Development / Angular

4-5 minutes

Angular Marble Testing: A Brief Introduction

marble testing

Working with Angular implies a wide use of reactive programming, that is, programming with asynchronous data streams. Angular components often operate with several observable streams that have overlapping sequences of values and errors. Testing such scenarios using common methods is often complicated. RxJS Marble Testing is much more helpful in these cases.

In this article, we’ll try to explain what is marble testing and how it works.

  1. What is marble testing?
  2. ‘Jasmine-marbles’ library
  3. Example

What is marble testing?

Marble testing allows you to test asynchronous RxJS code synchronously and step-by-step with the help of RxJS TestScheduler test utility and using virtual time steps.

There are also marble diagrams which demonstrate what is happening with a particular operation in the observable stream.

angular marble testing

ASCII marble diagrams are an alternative way to describe the observable stream. For instance, ASCII diagram a–bc—d–#–| corresponds to the marble diagram on the image above.

A marble diagram in TestScheduler is a string of characters that represents events which occur during the virtual time. Time progresses through ‘frames’. The first character represents a zero ‘frame’ or the beginning of time.

  • “-” — 10 ‘frames’ of time passing
  • “|” — the successful completion of the observable stream. Corresponds to the complete() method.
  • “#” — the error completion of the observable stream. Corresponds to the error() method.
  • “a” (or any other alphanumeric character) — a value emitted by the observable stream. Corresponds to the next() method.
  • “()” — a grouping of several events that should occur synchronously in one ‘frame’. Allows you to group the emitted value with the end of stream or an error.
  • “^” — a subscription point (only for hot observables). It’s a ‘zero frame’ for the observable, so each frame before ^ will be negative. Negative time may be needed during ‘ReplaySubjects’ testing.
  • “!” —  the end of a subscription point.

ASCII marble diagrams are used to create so-called hot and cold observable streams, which, in their turn, are used as mock-ups in test-waiting methods. Let’s discuss this next.

Jasmine-marbles library

‘Jasmine’ provides the ‘npm’ package ‘jasmine-marbles’. It is a library for `TestScheduler` that significantly simplifies marble testing. This package is not included in the Angular CLI test suite, so it must be installed separately: ‘$ npm install jasmine-marbles –save-dev’

‘Jasmine-marbles’ provides two methods for creating observables out of marble diagrams:

  • ‘cold (marbles: string, values ?: object, errors ?: any)’ – the subscription starts when the test begins
  • ‘hot (marbles: string, values ?: object, errors ?: any)’ – it’s already “running” when the test begins; the subscription starts with the “^” character.

ASCII marble diagram is passed to both methods as the first argument. The second argument is an optional object matching the characters in the diagram and their values. If this object is absent, the created observable will be emitting the characters from the diagram. If there is an error in the stream, it will be passed as the third argument.

For instance, ‘cold(‘–a–b–|’, {a: 10, b: ‘hello’})’ will create a cold observable stream that will emit value 10 at 30ms, value ‘hello’ at 60ms and will end at 90ms.

Thanks to the work of the test scheduler, the test is synchronous (`fakeAsync ()` is not used).

Example

Let’s take a look at a common example – a counter component.  

We have the following requirements to the component:

  1. The component must have two buttons (‘Up’ and ‘Down’) and a counter.
  2. The counter should start at 0.
  3. Clicking the ‘Up’ button should add 1 to the counter; clicking the ‘Down’ button should subtract 1 from the counter.

Now, let’s create a component test considering the above requirements:

marble testing code

Next, we need to describe the logic behind the way the component works with the observable stream using marble diagrams:

  1. Stream of events after pressing the ‘Up’ button
  2. Stream of events after pressing the ‘Down’ button.
  3. The resulting stream.

Now, based on the marble diagrams, let’s create the observable streams using the ‘cold ()’ method from the `jasmine-marbles` library. We need this to verify whether the resulting observable stream of the counter corresponds to the observable streams of click events on the ‘Up’ and ‘Down’ buttons.

After that, we can implement a component code that will successfully pass the tests.

import { Component } from '@angular/core';
import { merge, Observable, Subject } from 'rxjs';
import { mapTo, scan, startWith } from 'rxjs/operators';

@Component({
 selector: 'app-counter',
 template: `
   <button (click)="up$.next()">Up</button>
   <button (click)="down$.next()">Down</button>
   <div class="counter">{{counter$ | async}}</div>
 `,
})
export class CounterComponent {
 counter$: Observable<number>;
 up$ = new Subject();
 down$ = new Subject();

 constructor() {
   const {up$, down$} = this;
   this.counter$ = this.getCounter({up$, down$});
 }

 getCounter({up$, down$}) {
   return merge(
     up$.pipe(mapTo(1)),
     down$.pipe(mapTo(-1))
   ).pipe(
     startWith(0),
     scan((x, y) => x + y)
   )
 }
}

To receive a whole code from this article, fill out the form below and click Send Download Link button.

Name *

Email *

Conclusion

As mentioned, the described methodology is indeed very effective and it’s the best option for testing asynchronous RxJS code. It will help you easily test even the most complex networks of observable streams in various Angular components of the application.

Looking for professional app developers for your next project?

Mykola is a web developer at GBKSOFT. His professional experience includes 10+ years of software development with a focus on Angular and React in recent years. Mykola’s hobby is to learn rare features and share his knowledge with the tech community.


Leave a comment
Close

Leave a Reply


Similar Blog Articles

Development

Pros and Cons of JavaScript Full Stack Development

Web development projects usually require making numerous tech decisions and the most crucial of them are: what technologies to use for the frontend (i.e. client-side) and backend (i.e. server-side) development. And the question is not that easy as it may seem. The list of possible options becomes longer as the new technologies emerge. And if...

Rating — 5 (4 voices)
What are the stages of software testing in GBKSOFT

Development

The Guide to Software Testing Process

Some people thought that avoiding testing stage of the software development was a good idea. They thought it would save thier budget. How wrong they were…

Rating — 5 (1 voice)

Categories

All articles Business Company News Development Marketing StartUp App Ideas UI and Design

Tell us

About your project

We’ll estimate your project and give first advice within 24 hours!

We use cookies to improve your experience with our site, including analytics and personalization. By continuing to use the service, you agree to our use of cookies as described in the Privacy Policy.

Testimonials

Jonathan
More good work from team GBKSOFT. All well executed. The support within GBKSOFT is excellent. Communication is good too, spoken English as well as written. Support
Raphael Lasry
My Project with GBKSOFT gave me the ability to develop my software while keeping a busy schedule. Ana, who was my project manager, was very professional and was always understanding of my vision and what I wanted. I would recommend GBKSOFT again to any other company or person who has a vision for their web application. Thank you GBKSOFT! Recommend
Tao
GBKSOFT did a good job to manage the project. They put in a good effort to communicate with us and make it easier for us to communicate with developers. Good Job
13
App Futura ExtractGood FirmsClutchAwwwards