Testing an Angular 2 component with simulated dependencies

Attempting to test an Angular 2 component with fake dependencies has been a challenge.

Currently developing a simple TODO app using Ng2 and Redux, I have encountered a situation where one of my components includes an instance of the redux app store.

In order to mock this object and spy on its subscribe method, I have come up with the following solution:

import { TestComponentBuilder } from '@angular/compiler/testing';
import {HomeComponent} from './home.component';
import {provide} from '@angular/core';
import {
    it,
    expect,
    inject,
    describe,
    async,
    beforeEachProviders
} from '@angular/core/testing';


class MockAppStore {

    title: String;
    constructor() {
        this.title = 'plouf';
    }
    subscribe(callback) {
        callback();
    }
}

describe('HomeComponent', () => {

    beforeEachProviders(() => [
        provide('AppStore', { useValue: MockAppStore })
    ]);

    it('should call the dispatch method of the appStore', async(inject([TestComponentBuilder],
        (tsb: TestComponentBuilder) => {
            tsb.createAsync(HomeComponent).then((fixture) => {
                // Given
                const component = fixture.componentInstance;
                spyOn(component.appStore, 'subscribe');

                // When
                fixture.detectChanges();

                // then
                expect(component.appStore.subscribe).toHaveBeenCalled();
            });
        })));
});

This is meant to test the following component :

import {Component, Inject} from '@angular/core';

@Component({
    selector: 'as-home',
    templateUrl: 'app/home/home.html',
    styleUrls: [
        'app/home/home.css'
    ]
})
export class HomeComponent {

    appStore: any;
    constructor( @Inject('AppStore') appStore: any) {
        this.appStore = appStore;
        this.appStore.subscribe(state => {
            console.log(state);
        });
    }
}

Unfortunately, the test does not pass and the error message is not very clear:

PhantomJS 2.1.1 (Windows 8 0.0.0) HomeComponent should call the dispatch method of the appStore FAILED
        invoke@C:/Project/angular2/kanboard/node_modules/zone.js/dist/zone.js:323:34
        run@C:/Project/angular2/kanboard/node_modules/zone.js/dist/zone.js:216:50
        C:/Project/angular2/kanboard/node_modules/zone.js/dist/zone.js:571:61
        invokeTask@C:/Project/angular2/kanboard/node_modules/zone.js/dist/zone.js:356:43
        runTask@C:/Project/angular2/kanboard/node_modules/zone.js/dist/zone.js:256:58
        drainMicroTaskQueue@C:/Project/angular2/kanboard/node_modules/zone.js/dist/zone.js:474:43
        invoke@C:/Project/angular2/kanboard/node_modules/zone.js/dist/zone.js:426:41
PhantomJS 2.1.1 (Windows 8 0.0.0): Executed 16 of 16 (1 FAILED) (0.48 secs / 0.518 secs)
Remapping coverage to TypeScript format...
Test Done with exit code: 1
[08:28:55] 'unit-test' errored after 7.27 s
[08:28:55] Error: 1
    at formatError (C:\Project\angular2\kanboard\node_modules\gulp\bin\gulp.js:169:10)

...and so on...

If you have any insights on why the test is failing or have suggestions for best practices when mocking rxjs observable/subscriptions, your help would be greatly appreciated.

Thank you.

Answer №1

It seems like the issue lies within your assumption. One potential resolution is to test it this way:

expect(component.appStore.subscribe).toHaveBeenCalled();

Rather than:

expect(component.appStore).toHaveBeenCalled();

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Resolving problems with sending JSON data to server using AngularJS $http post

My challenge is sending JSON data from an AngularJS front-end form to a server running Express/Node.js, and then storing it in MongoDB. The issue I'm facing is that I can't seem to successfully send the data over. When I check the data on the ser ...

Utilize various algorithms to identify the predominant object based on multiple parameters in TypeScript

Having collected student profiles with scores in various subjects such as physics, chemistry, and math, I am looking to identify a group of dominant students based on their individual subject scores. For instance: let students = [{name: "A", phy: 70, chem ...

The compatibility issue between Angular's ngModel and Value in input components

Encountering a challenge with the angular form. My objective is to create a form pre-filled with default values that can be edited. Upon validation, the form should submit the data to the MySQL database. Below is the component.html code: <form #adopt=& ...

Evaluating the functionality of a pipeline that relies on various services

There is a custom pipe in my Angular application that sanitizes HTML, defined as follows: import { Pipe, PipeTransform } from '@angular/core'; import { DomSanitizer } from '@angular/platform-browser'; @Pipe({ name: 'sanitiseH ...

Title of a property left `undetermined`

When dealing with a class, it is possible to retrieve the name of a defined property or function. For instance, the class name can be obtained using the following code snippet... console.log(`${this.constructor.name} is my name); Similarly, the name of a ...

Struggling with coding an array of images in Angular JS

I am having trouble displaying the images as thumbnails and full images for each "gem." The Angular tutorial I followed did not provide enough detail on how to do this. Here is my HTML code: <!DOCTYPE html> <html ng-app="store"> <head> ...

What is the best method of transferring all procedures from frida javascript rpc.exports to python?

I have a JavaScript file containing rpc.exports rpc.exports = { callfunctionsecret: callSecretFun, callfunctionsomethingelse: callSomethingElse, } I am trying to retrieve a list of all these functions in Python, but I have been unable to find a so ...

Tips for capturing the Three.js model file content and assigning it to a variable

After exporting a model from Blender to Three.js, the resulting file contains JSON data. There are two methods I know of for loading this model: var loader = new THREE.JSONLoader() var material = new THREE.MeshPhongMaterial({color: '#8080a0'}) ...

Utilizing jQuery or JavaScript to convert a PHP return value into an array for use in JavaScript

Is there a way to retrieve a JavaScript array from a PHP return value? For example, if a PHP script called 'makeArray.php' returns "first", "second", "third" (without the single quotes), how can I use this array in JavaScript to alert "second"? ...

Encounter the error "Attempting to access object using Object.keys on a non-object" when attempting to retrieve all fields in request.body in Node.js?

I am working with a piece of code that handles the PUT method: module.exports.addRoutes = function(server) { //PUT server.put('/api/public/place/:id', function(request, response) { //this is just for testing, please do not care ...

CombineReducers takes all the reducer content and unpacks it into a single reducer

As I work on developing a small application, I am contemplating the best strategy for organizing reducers within it. My objective is to retrieve JSON data from the application state and structure it as shown below: { "fruits": [ {"appl ...

Selecting dynamic routes with VueJS components

My Vue instance looks like this: new Vue({ el: '#Application', router: Router, components: { 'ExampleDepartment', Application }, data: function() { return { } } }); In my application file, ...

When utilizing a node.js TCP socket to receive and send modified data, the functionality only operates successfully on the initial attempt

I am attempting to create a node.js TCP socket that will receive data, modify it, and then send it back. I found a helpful example on Stack Overflow here: . The example works perfectly as is, but when I add my own code to send data back, it only works for ...

React mapped checkboxes are displaying all elements from the array, not just the ones that are checked

Visual: The form is displayed on the left, while the outputs appear on the right I'm currently working on implementing a checkbox array map in React to showcase the features of a specific item. However, I'm facing an issue where all array elemen ...

Tips for sending data other than strings in a GET request to a web API

When calling an asp.net mvc web api controller action from an angular 2 application, I have the ability to accept objects from the call using a post method. Here is an example: [Route("api/getItems")] [HttpPost] public ReturnObject GetItems(Da ...

Personalized pop-up experience with AngularJS

I am currently working on creating a filter in AngularJS without relying on jQuery. To achieve this, I am using a custom directive to generate a popup that includes a checkbox. However, I have encountered a couple of issues. 1. I have created two popups u ...

Creating a Jquery plugin that triggers an "onclick" event for various elements

I am in the process of developing a jQuery plugin that can detect click events on multiple elements with the same ID. // Event listener for clicks base.$el.click(function (event) { event.preventDefault(); alert("You clicked!"); }); Currently, t ...

Encountering Kubernetes Ingress Error: 502 Bad Gateway - Connection Refused

I am facing an issue while trying to access my Angular front-end deployed on an AKS cluster at Path / with the service named lawyerlyui-service. The cluster is using nginx deployed via HELM with the official chart () I have other backend .net core services ...

Utilizing ng-class within select alongside ng-options in Angular versions 1.4 and above

My issue is similar to the problem described in this post : How to use ng-class in select with ng-options I am looking to customize specific options in a select element using CSS. To illustrate, I have an array of people like so : var persons = [ {Name:& ...

Retrieving the necessary data from my object to perform a sum calculation in angular

Having trouble retrieving an attribute from an array in my code. In my .ts file, I am fetching data from my backend endpoint like this: export class PostFeedComponent implements OnInit { data: any = {}; constructor(private http: HttpClient) { t ...