Make sure that spyOnProperty is used to create configurable properties using Object.defineProperty

After upgrading to Angular 9 (from 8.1) and Typescript 3.7 (from <3.6), I've come across an issue with the spyOnProperty method.

This is how my service looks:

class Backend {
  public get baseURL(): string {
    return 'http://baseurl.com/';
  }
}

Previously, my test that used spyOnProperty worked fine:

spyOnProperty(backend, 'baseURL', 'get').and.returnValue('http://new');

However, now I'm facing this error:

Error: <spyOnProperty> : baseURL is not declared configurable
Usage: spyOnProperty(<object>, <propName>, [accessType])

I understand that I need to set configurable: true using Object.defineProperty, as the error seems to be related to:

if (!descriptor.configurable) {
  throw new Error(
    getErrorMsg(propertyName + ' is not declared configurable')
  );
}

The descriptor is created by

descriptor = Object.getOwnPropertyDescriptor(proto, methodName);

In Javascript, you would do something like this:

Object.defineProperty(backend.prototype, 'baseURL', {value: 'http://new', configurable: true});

But my question is, how can I achieve the same in Typescript? Attempting to use Object.defineProperty again results in a

defineproperty Cannot redefine property
error, which makes sense given the initial check in place.

I tried using the suggested configurable decorator described here:

function configurable(value: boolean) {
    return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
        descriptor.configurable = value;
    };
}

Unfortunately, this approach didn't work for me. Also, when debugging inside the mentioned method, I noticed that descriptor.configurable was already set to true before assigning the value. So, I'm unsure of what exactly is causing the original error in my tests.

Answer №1

I realized I was missing some key information when it came to setting up my tests. In order to create an instance of the services I needed, I decided to utilize ts-mockito to generate an instance() for each class.

Upon further inspection, I discovered that the use of instance() may have been causing certain properties to be non-configurable.

In essence:

service = new Service(instance(new Backend));

Was revised to:

service = new Service(new Backend);

This adjustment successfully resolved the issue at hand.

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

Error message: The function ctorParameters.map is not defined

I am currently experimenting with implementing dragula in my angular2 application. Here is the snippet from my code containing the app.module: import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@ang ...

The yarn.lock file is failing to reflect the updated version of a dependency in package.json, even after running the yarn install command or simply using yarn to install the

Within the project's repository, both the package.json and yarn.lock files are already present. I am currently in the process of upgrading a specific package from version 2.0.14 to version 2.0.16. After running either yarn install or simply yarn, I n ...

Exploring the power of AngularJS and Jasmine: testing multiple instances of a service in action

Currently, I am immersing myself in the book "Mastering Web Application Development with AngularJS" and came across an example test named 'Aggregating callbacks.' The specific example causing me troubles involves the Person object: var Person = ...

Triggering the detection of changes even when the value linked to remains the same

I'm facing an issue with a component that is supposed to react to changes in input controls by reformatting the input and removing certain characters. If the removed character corresponds to the previous value, the component fails to detect any change ...

Attempting to simulate the behavior of Angular2 Token during testing

Currently, I am working on obtaining a token that is required for API authentication to retrieve a list. My approach begins with importing the angular2-token library: import { Angular2TokenService } from 'angular2-token'; After this, I include ...

Array method involving variable type alterations

Is this a TypeScript bug or am I missing something? Variable type changes based on whether it's in an array method or not. This causes type issues and the only workaround I can think of is an additional typecast in a function call. const fn = (arg: st ...

Is there a way to transform an angular 2 app.module into ES6 format?

import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { HttpModule } from '@angular/http'; //specific imports remov ...

Error code TS7053 occurs when an element implicitly has an 'any' type because a string expression cannot be used to index an empty object

I have implemented a code snippet that sorts items into groups based on their first character. For example, if the array of item looks like this: {name: 'Foo'} {name: 'Bar'} {name: 'Baz'} The expected result should be: B: ...

Tips for organizing an NPM package containing essential tools

Currently facing the challenge of creating an NPM package to streamline common functionality across multiple frontend projects in our organization. However, I am uncertain about the correct approach. Our projects are built using Typescript, and it seems th ...

Configure Typescript to skip errors for a specific file

Is there a way to suppress TypeScript errors for specific files using the tsconfig.json file? I am aware of the exclude property mentioned on the TypeScript website, but that's not exactly what I'm looking for. As it's explained: If a fil ...

Error: The 'Window' object is not defined. The use of Client in NextJS13 is not

I've been attempting to integrate NextJS 13 with react-leaflet, but I keep encountering the error "window is not defined" when running my component. I attempted using the "use client" declaration at the beginning of the file and adding a check for "ty ...

The exportAs attribute is not specified as "ngForm" for any directive

Encountered an error while attempting to test the LoginComponent PhantomJS 2.1.1 (Linux 0.0.0): Executed 3 of 55 (1 FAILED) (0 secs / 0.307 secs) PhantomJS 2.1.1 (Linux 0.0.0) LoginComponent should create FAILED Failed: Uncaught (in promise): Error: Templ ...

Issue with Angular 5 - Deselect all checkboxes not reflecting in the UI

I am currently working on integrating a reset button into a Reactive form in Angular 5. The reset functionality works flawlessly for all form fields, except for the dynamically created multiple checkboxes. Although it seems like the reset operation is hap ...

Reasons behind Angular HttpClient sorting JSON fields

Recently, I encountered a small issue with HttpClient when trying to retrieve data from my API: constructor(private http: HttpClient) {} ngOnInit(): void { this.http.get("http://localhost:8080/api/test/test?status=None").subscribe((data)=> ...

I implemented progress bars in Angular 2 that have changing maximum values. The service updates the maximum value for each bar dynamically. Currently, the progress bars are functioning at 100% capacity

this.games=[ {"val":50, "name":"Articlescontributed","max":35}, {"val":30 ,"name":"Articlesrated", "max":999}, {"val":20, "name":"Views", "max":35}, {"val":30, "name":"Ratings", "max":35}, {"val":20, "name":"Follower", "max":200}, { ...

The type 'ElementTypes' cannot be assigned to type 'ElementTypes.word'

After recently learning TypeScript, I encountered an error that made me think I need to write a narrower type for it or something along those lines. Here is the code snippet in question: enum ElementTypes { h1 = 'H1', word = "WORD" ...

Is there a way to determine the specific type of a property or field during runtime in TypeScript?

Is there a way to retrieve the class or class name of a property in TypeScript, specifically from a property decorator when the property does not have a set value? Let's consider an example: class Example { abc: ABC } How can I access the class or ...

Understanding Vue.js - encountering the error message "property or method is not defined"

Recently, I've come across an issue that seems to be common among many people, but for some reason, I am unable to find a solution despite looking at similar questions. The problem arises when I use a v-for in a Vue Component and the array value cons ...

Establishing the placement of map markers in Angular

Currently, I am in the process of developing a simple web application. The main functionality involves retrieving latitude and longitude data from my MongoDB database and displaying markers on a map, which is functioning correctly. However, the issue I&apo ...

Obtain the value of a jQuery variable in TypeScript

I'm attempting to utilize the jQuery $ajax() function to call a Web API. After making the call, I am trying to figure out how to store the result in my TypeScript variable. $.ajax({ method: "POST", url: 'URL', data: { email:'exa ...