Angular testing with Jasmine and TypeScript

I've been attempting to create some Angular Controller tests for my App using TypeScript for a few days now, but haven't had any success. Let me start by saying that this is my first time writing tests in Jasmine. My issue is that I'm having trouble mocking a dependent service in order to test the controller. Any guidance or pointing me in the right direction would be greatly appreciated.

Angular Module :

 angular.module('some.module', ['ui.router', 'ngAnimate', 'ui.bootstrap', 'pascalprecht.translate', 'ngCookies', 'smart-table']);

Angular Controller :

module App.Controllers {

export class TestController{
    static $inject = ["$scope","SomeService"];
    WhatController: () => string;
    constructor(private $scope: App.IAppScope, private SomeService) {
        var vm = this;
        vm.WhatController = function (): string {
            return SomeService.someAction();
        };
    }
}

angular.module("some.module").controller("TestController", TestController);

}

Angular Service :

module App.Services {

export class SomeService{
    httpService: ng.IHttpService;
    static $inject = ["$http"];
    someAction: () => any;

    constructor($http: ng.IHttpService) {
        var service = this;
        service.someAction= () => {
           return "test";
        }
    }
}

factory.$inject = ['$http'];
function factory($http: ng.IHttpService) {
    return new SomeService($http);
}

angular.module('some.module').factory('SomeService', factory);

}

Karma File :

    module.exports = function (config) {
    config.set({
        basePath: 'Scripts',
        frameworks: ['jasmine', 'jasmine-matchers'],
        files: [

            { pattern: 'angular.js', included: true },
            { pattern: 'angular-mocks.js', included: true },
            { pattern: 'angular-ui-router.js', included: true },
            { pattern: 'angular-ui/ui-bootstrap-tpls.js', included: true },
            { pattern: 'angular-animate.js', included: true },
            { pattern: 'angular-translate.js', included: true },
            { pattern: 'angular-translate-loader-url.js', included: true },
            { pattern: 'angular-cookies.js', included: true },
            { pattern: 'smart-table.js', included: true },

            '../app/app.module.js',
            '../app/pages/**/*.controller.js',

            //Here are controller files
            { pattern: '../app/pages/**/*.spec.js', included: true },

        ],
        exclude: ['**/*min.js'],
        preprocessors: {
            '../app/pages/**/*.controller.js': ['coverage'],
        },

        reporters: ['progress', 'coverage'],
        port: 9876,
        colors: true,
        logLevel: config.LOG_INFO,
        autoWatch: true,
        browsers: ['PhantomJS'],
        singleRun: true,

        coverageReporter: {
        type : 'html',
        dir : 'coverage/'
    }
    })
}

Test :

    'use strict';
describe("complaints.controller.test", () => {
    var $http: ng.IHttpService;
    var mockSomeServices: App.Services.SomeServices;
    var mock = angular.mock;


    beforeEach(() => {
        mock.module('ui.router');
        mock.module('ngAnimate');
        mock.module('ui.bootstrap');
        mock.module('pascalprecht.translate');
        mock.module('ngCookies');
        mock.module('smart-table');
      });

    //This don't work mockSomeServices  is undefined
    beforeEach(mock.inject((_$http_, $injector) => {
        $http = _$http_;
        mockSomeServices = $injector.get('SomeServices');
    }));

   //This also don't work mockSomeServices  is undefined
    beforeEach(mock.inject((_$http_, $injector, SomeServices) => {
        $http = _$http_;
        mockSomeServices = SomeServices;
    }));
});

Answer №1

To simulate a service, the process involves:

angular.mock.module(($provide: ng.auto.IProvideService): void => {
    $provide.constant("SomeService", SomeService = { });
});

When working with your controller, it's important to note that you shouldn't mock the service but rather track if it was invoked by using a spy on the service.

spyOn(SomeService, "someAction");

If you need the service to provide data for validation in the controller, you can do so with:

spyOn(SomeService, "someAction").and.returnValue(/* data */);

Subsequently, verify that the service was utilized and that the data matches your expectations:

expect(SomeService.someAction).toHaveBeenCalled();
expect(yourController.someValue).toEqual("someValue");

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

Add to Firebase reference using AngularFire

Imagine I'm constructing a never-ending scroll of articles. The article's ID is obtained from the URL: var id = $stateParams.id; I aim to startAt that specific index in my Firebase collection and restrict it to 10 items: var limit = 10; var a ...

"Geolocation within the boundary of a map: what's the message

Can text be placed inside a shape using ng-map? <ng-map default-style="true" zoom="18" center="53.25564575, -113.81401062" map-type-id="SATELLITE"> <shape name="rectangle" editable="true" draggable="true" bounds="[[53.2559199723254, ...

How to access the types of parameters in a function type

I am working on a function that takes a value and default value as arguments. If the value is a boolean, I want the return type to match the type of the default value. Here is the function I have: export type DetermineStyledValue<T> = ( value: str ...

Tips for efficiently inserting large amounts of data using a select subquery

I'm currently using Sequelize in my project and encountering difficulties in converting a simple query into Sequelize syntax. Furthermore, I am also exploring ways to efficiently perform bulk inserts for this particular query. The query in question i ...

What is the process for importing a TypeScript module in the StackBlitz editor?

When I enter the editor at Stackblitz.com and start a new Angular project, it comes with default files and folders already set up. In the "Dependencies" section, I decide to add shortid. So, I input that in the designated box and it begins loading the cor ...

Applying the spread operator in the map function for copying objects

In my Angular application, I am attempting to copy an object and add a new property using the spread operator. To add the new property, I have created a method called 'addNewProperty(name)' which returns the property and its value. However, when ...

How to ensure Service is loaded before App Component in Angular 6?

My Data service is responsible for fetching the JSON Object value, however all components load before the data service finishes loading. This results in undefined values when I call the service method from components. ...

Error in React.tsx Material UI Tab - Avoid using curly braces "{}" as a data type

Currently, I am working on a React TS project and facing an issue while trying to import the Material UI tabs for scrollable functionality. The specific Tabs/Scrollable Tabs example from Material-UI documentation is what I'm referring to: https://mate ...

AngularJS: displaying or concealing elements while updating the user interface

As I work on troubleshooting a problem with my angular app, I am facing an issue where the UI does not update smoothly. The $http.get method is used to initialize the model and it takes a few seconds to fetch data from the server. To provide a seamless use ...

The script is unable to locate the property 'indexOf' because it is undefined

Searching for a specific value in an array using ui-select to capture values. A function is created to verify the existence of the value, which works perfectly fine. However, the console displays multiple instances of the error 'Cannot read property & ...

Tips for organizing a multi-dimensional array based on various column indexes

I am looking to organize a multidimensional array by multiple column index. Take, for instance, the test data provided below: var source = [ ["Jack","A","B1", 4], ["AVicky","M", "B2", 2], [ ...

Accepting undefined in rest parameter of typescript

I'm struggling with an exercise involving Function parameters: The maximum function below has the wrong type. To allow undefined in the rest arguments, you need to update the type of the rest parameter. Fortunately, you don't have to change the ...

Guide on dividing a URL string in Angular framework

Is there a way to include a value directly in the URL, like so: http://example.com/component/july2021 I need to extract july2021 from the component and separate it into "july" and "2021". How can I achieve this? ...

Accessing a TypeScript variable in Angular2 and binding it to the HTML DOM

While I have experience with AngularJS, delving into Angular2 has proven to be a new challenge for me. Understanding the ropes is still a work in progress. In my list of files, there's a home.ts and a home.html Within my home.ts, this snippet reside ...

`The flaw in filtering logic - an analysis`

Looking to find matching records within two Lists. We have a List called allAnimals with attributes like animalId, and another List named domesticAnimals also containing animalId. The goal is to compare the two lists and create a new list where the anima ...

Resolving circular dependencies caused by APP_INITIALIZER

My AuthenticationService is responsible for loading the AngularFirestore and is loaded in the RootComponent. All app modules are lazily loaded within the RootComponent (which contains the main router-outlet). However, several sub-modules also load the Ang ...

Is it possible to implement the SCSS CSS preprocessor in Angular 1.6.6, even though it is already utilizing LESS as the current CSS preprocessor?

Is it necessary to compile SCSS and Stylus files into CSS before importing them into my Angular version 1 app? Are there any other alternatives available? Context: I have two applications, one using Angular 4 with SCSS and the other using Angular 1 with L ...

Tips on boosting the speed and user-friendliness of your AJAX/REST application

Exploring the Essential Requirements of an Application I am currently developing a comprehensive application using AngularJS (but it could be any framework). This application interacts with a server built on Google App Engine through REST technology. Th ...

What is the process for customizing the favicon on the generator-angular-fullstack platform?

Is it possible to customize the favicon for the generator-angular-fullstack project? I'm currently working on deploying the initial project from https://github.com/DaftMonk/generator-angular-fullstack, which is known as one of the most popular Yeoman ...

Steps for adding an npm package to your project locally

After obtaining the demo and ng2-archwizard, I am eager to customize the source code for ng2-archwizard locally and install it in the demo project. To achieve this, my initial attempt was to use npm link following these steps: I made modifications withi ...